]> git.donarmstrong.com Git - dsa-puppet.git/commitdiff
try with modules from master
authorMartin Zobel-Helas <zobel@debian.org>
Fri, 3 Jul 2015 15:16:07 +0000 (15:16 +0000)
committerMartin Zobel-Helas <zobel@debian.org>
Fri, 3 Jul 2015 15:16:07 +0000 (15:16 +0000)
Signed-off-by: Martin Zobel-Helas <zobel@debian.org>
109 files changed:
3rdparty/modules/keystone/CHANGELOG.md [new file with mode: 0644]
3rdparty/modules/keystone/Gemfile
3rdparty/modules/keystone/LICENSE
3rdparty/modules/keystone/README.md
3rdparty/modules/keystone/checksums.json [deleted file]
3rdparty/modules/keystone/examples/apache_dropin.pp
3rdparty/modules/keystone/examples/apache_with_paths.pp
3rdparty/modules/keystone/examples/ldap_full.pp
3rdparty/modules/keystone/examples/ldap_identity.pp
3rdparty/modules/keystone/files/httpd/keystone.py
3rdparty/modules/keystone/lib/puppet/provider/keystone.rb
3rdparty/modules/keystone/lib/puppet/provider/keystone_endpoint/openstack.rb
3rdparty/modules/keystone/lib/puppet/provider/keystone_role/openstack.rb
3rdparty/modules/keystone/lib/puppet/provider/keystone_service/openstack.rb
3rdparty/modules/keystone/lib/puppet/provider/keystone_tenant/openstack.rb
3rdparty/modules/keystone/lib/puppet/provider/keystone_user/openstack.rb
3rdparty/modules/keystone/lib/puppet/provider/keystone_user_role/openstack.rb
3rdparty/modules/keystone/lib/puppet/provider/openstack.rb [deleted file]
3rdparty/modules/keystone/lib/puppet/type/keystone_endpoint.rb
3rdparty/modules/keystone/lib/puppet/type/keystone_role.rb
3rdparty/modules/keystone/lib/puppet/type/keystone_service.rb
3rdparty/modules/keystone/lib/puppet/type/keystone_tenant.rb
3rdparty/modules/keystone/lib/puppet/type/keystone_user.rb
3rdparty/modules/keystone/lib/puppet/type/keystone_user_role.rb
3rdparty/modules/keystone/lib/puppet/util/openstack.rb [deleted file]
3rdparty/modules/keystone/manifests/client.pp
3rdparty/modules/keystone/manifests/db/mysql.pp
3rdparty/modules/keystone/manifests/db/postgresql.pp
3rdparty/modules/keystone/manifests/dev/install.pp
3rdparty/modules/keystone/manifests/endpoint.pp
3rdparty/modules/keystone/manifests/init.pp
3rdparty/modules/keystone/manifests/ldap.pp
3rdparty/modules/keystone/manifests/params.pp
3rdparty/modules/keystone/manifests/python.pp
3rdparty/modules/keystone/manifests/resource/service_identity.pp
3rdparty/modules/keystone/manifests/roles/admin.pp
3rdparty/modules/keystone/manifests/service.pp
3rdparty/modules/keystone/manifests/wsgi/apache.pp
3rdparty/modules/keystone/metadata.json
3rdparty/modules/keystone/spec/acceptance/basic_keystone_spec.rb [new file with mode: 0644]
3rdparty/modules/keystone/spec/acceptance/nodesets/default.yml [new file with mode: 0644]
3rdparty/modules/keystone/spec/acceptance/nodesets/nodepool-centos7.yml [new file with mode: 0644]
3rdparty/modules/keystone/spec/acceptance/nodesets/nodepool-trusty.yml [new file with mode: 0644]
3rdparty/modules/keystone/spec/classes/keystone_client_spec.rb
3rdparty/modules/keystone/spec/classes/keystone_cron_token_flush_spec.rb
3rdparty/modules/keystone/spec/classes/keystone_db_mysql_spec.rb
3rdparty/modules/keystone/spec/classes/keystone_db_postgresql_spec.rb
3rdparty/modules/keystone/spec/classes/keystone_endpoint_spec.rb
3rdparty/modules/keystone/spec/classes/keystone_ldap_spec.rb
3rdparty/modules/keystone/spec/classes/keystone_logging_spec.rb
3rdparty/modules/keystone/spec/classes/keystone_policy_spec.rb
3rdparty/modules/keystone/spec/classes/keystone_python_spec.rb
3rdparty/modules/keystone/spec/classes/keystone_roles_admin_spec.rb
3rdparty/modules/keystone/spec/classes/keystone_service_spec.rb
3rdparty/modules/keystone/spec/classes/keystone_spec.rb
3rdparty/modules/keystone/spec/classes/keystone_wsgi_apache_spec.rb
3rdparty/modules/keystone/spec/defines/keystone_resource_service_identity_spec.rb
3rdparty/modules/keystone/spec/shared_examples.rb
3rdparty/modules/keystone/spec/spec_helper.rb
3rdparty/modules/keystone/spec/spec_helper_acceptance.rb [new file with mode: 0644]
3rdparty/modules/keystone/spec/unit/provider/keystone_endpoint/openstack_spec.rb
3rdparty/modules/keystone/spec/unit/provider/keystone_role/openstack_spec.rb
3rdparty/modules/keystone/spec/unit/provider/keystone_service/openstack_spec.rb
3rdparty/modules/keystone/spec/unit/provider/keystone_spec.rb
3rdparty/modules/keystone/spec/unit/provider/keystone_tenant/openstack_spec.rb
3rdparty/modules/keystone/spec/unit/provider/keystone_user/openstack_spec.rb
3rdparty/modules/keystone/spec/unit/provider/keystone_user_role/openstack_spec.rb
3rdparty/modules/keystone/spec/unit/provider/openstack_spec.rb [deleted file]
3rdparty/modules/keystone/tests/site.pp
3rdparty/modules/openstacklib/CHANGELOG.md [new file with mode: 0644]
3rdparty/modules/openstacklib/Gemfile
3rdparty/modules/openstacklib/LICENSE
3rdparty/modules/openstacklib/README.md
3rdparty/modules/openstacklib/checksums.json [deleted file]
3rdparty/modules/openstacklib/lib/puppet/provider/aviator.rb [deleted file]
3rdparty/modules/openstacklib/lib/puppet/provider/openstack.rb [new file with mode: 0644]
3rdparty/modules/openstacklib/lib/puppet/provider/openstack/auth.rb [new file with mode: 0644]
3rdparty/modules/openstacklib/lib/puppet/provider/openstack/credentials.rb [new file with mode: 0644]
3rdparty/modules/openstacklib/lib/puppet/util/aviator.rb [deleted file]
3rdparty/modules/openstacklib/manifests/db/postgresql.pp [new file with mode: 0644]
3rdparty/modules/openstacklib/manifests/openstackclient.pp [new file with mode: 0644]
3rdparty/modules/openstacklib/manifests/policy/base.pp
3rdparty/modules/openstacklib/manifests/wsgi/apache.pp [new file with mode: 0644]
3rdparty/modules/openstacklib/metadata.json
3rdparty/modules/openstacklib/spec/acceptance/mysql_spec.rb [new file with mode: 0644]
3rdparty/modules/openstacklib/spec/acceptance/nodesets/default.yml [new file with mode: 0644]
3rdparty/modules/openstacklib/spec/acceptance/nodesets/nodepool-centos7.yml [new file with mode: 0644]
3rdparty/modules/openstacklib/spec/acceptance/nodesets/nodepool-trusty.yml [new file with mode: 0644]
3rdparty/modules/openstacklib/spec/acceptance/rabbitmq_spec.rb [new file with mode: 0644]
3rdparty/modules/openstacklib/spec/classes/openstacklib_policy_spec.rb
3rdparty/modules/openstacklib/spec/defines/openstacklib_db_mysql_host_access_spec.rb
3rdparty/modules/openstacklib/spec/defines/openstacklib_db_mysql_spec.rb
3rdparty/modules/openstacklib/spec/defines/openstacklib_db_postgresql_spec.rb [new file with mode: 0644]
3rdparty/modules/openstacklib/spec/defines/openstacklib_messaging_rabbitmq_spec.rb
3rdparty/modules/openstacklib/spec/defines/openstacklib_policy_spec.rb
3rdparty/modules/openstacklib/spec/defines/openstacklib_service_validation_spec.rb
3rdparty/modules/openstacklib/spec/defines/openstacklib_wsgi_apache_spec.rb [new file with mode: 0644]
3rdparty/modules/openstacklib/spec/fixtures/vcr/aviator/request/with_session.yml [deleted file]
3rdparty/modules/openstacklib/spec/fixtures/vcr/aviator/request/without_session.yml [deleted file]
3rdparty/modules/openstacklib/spec/fixtures/vcr/aviator/session/with_password.yml [deleted file]
3rdparty/modules/openstacklib/spec/fixtures/vcr/aviator/session/with_token.yml [deleted file]
3rdparty/modules/openstacklib/spec/functions/os_database_connection_spec.rb
3rdparty/modules/openstacklib/spec/shared_examples.rb [new file with mode: 0644]
3rdparty/modules/openstacklib/spec/spec_helper.rb
3rdparty/modules/openstacklib/spec/spec_helper_acceptance.rb [new file with mode: 0644]
3rdparty/modules/openstacklib/spec/unit/provider/aviator_spec.rb [deleted file]
3rdparty/modules/openstacklib/spec/unit/provider/openstack/auth_spec.rb [new file with mode: 0644]
3rdparty/modules/openstacklib/spec/unit/provider/openstack/credentials_spec.rb [new file with mode: 0644]
3rdparty/modules/openstacklib/spec/unit/provider/openstack_spec.rb [new file with mode: 0644]

diff --git a/3rdparty/modules/keystone/CHANGELOG.md b/3rdparty/modules/keystone/CHANGELOG.md
new file mode 100644 (file)
index 0000000..973da8f
--- /dev/null
@@ -0,0 +1,209 @@
+##2015-06-17 - 5.1.0
+###Summary
+
+This is a features and bugfixes release in the Juno series.
+
+####Features
+- Allow disabling or delaying the token_flush cron
+- Use openstackclient for keystone_* providers
+- Switch to TLSv1
+- Handle missing project/tenant when using ldap backend
+- Add support for LDAP connection pools
+- Support the ldap user_enabled_invert parameter
+- Tag packages with 'openstack'
+- Add ::keystone::policy class for policy management
+- New option replace_password for keystone_user
+- Set WSGI process display-name
+- Add native types for keystone paste configuration
+
+####Bugfixes
+- crontab: ensure the script is run with shell
+- service_identity: add user/role ordering
+- Fix password check for SSL endpoints
+- Add require json for to_json dependency
+- Sync keystone.py with upstream to function with Juno
+- Allow Keystone to be queried when using IPv6 ::0
+
+####Maintenance
+* spec: pin rspec-puppet to 1.0.1
+* Pin puppetlabs-concat to 1.2.1 in fixtures
+* Update .gitreview file for project rename
+
+##2014-11-24 - 5.0.0
+###Summary
+
+This is a backwards-incompatible major release for OpenStack Juno.
+
+####Backwards-incompatible changes
+- Update token driver, logging, and ldap config parameters for Juno
+- Make UUID the default token provider
+- Migrate the keystone::db::mysql class to use openstacklib::db::mysql, adding
+  dependency on openstacklib
+
+####Features
+- Change admin_roles parameter to accept an array in order to configure
+  multiple admin roles
+- Add new parameters to keystone class to configure pki signing
+- Add parameters to control whether to configure users
+- Deprecate the mysql_module parameter
+- Enable setting cert and key paths for PKI token signing
+- Add parameters for SSL communication between keystone and rabbitmq
+- Add parameter ignore_default_tenant to keystone::role::admin
+- Add parameter service_provider to keystone class
+- Add parameters for service validation to keystone class
+
+####Bugfixes
+- Install python-ldappool package for ldap
+- Change keystone class to inherit from keystone::params
+- Change pki_setup to run regardless of token provider
+- Stop managing _member_ role since it is created automatically
+- Stop overriding token_flush log file
+- Change the usage of admin_endpoint to not include the API version
+- Allow keystone_user_role to accept email as username
+- Add ability to set up keystone using Apache mod_wsgi
+- Make keystone_user_role idempotent
+- Install python-memcache when using token driver memcache
+
+##2014-10-16 - 4.2.0
+###Summary
+
+This is a feature and bugfix release in the Icehouse series.
+
+####Features
+- Add class for extended logging options
+- Add parameters to set tenant descriptions
+
+####Bugfixes
+- Fix rabbit password leaking
+- Fix keystone user authorization error handling
+
+##2014-06-19 - 4.1.0
+###Summary
+
+This is a feature and bugfix release in the Icehouse series.
+
+####Features
+- Add token flushing with cron
+
+####Bugfixes
+- Update database api for consistency with other projects
+- Fix admin_token with secret parameter
+- Fix deprecated catalog driver
+
+##2014-05-05 - 4.0.0
+###Summary
+
+This is a major release for OpenStack Icehouse but contains no API-breaking
+changes.
+
+####Features
+* Add template_file parameter to specify catalog
+* Add keystone::config to handle additional custom options
+* Add notification parameters
+* Add support for puppetlabs-mysql 2.2 and greater
+
+####Bugfixes
+- Fix deprecated sql section header in keystone.conf
+- Fix deprecated bind_host parameter
+- Fix example for native type keystone_service
+- Fix LDAP module bugs
+- Fix variable for host_access dependency
+- Reduce default token duration to one hour
+
+##2014-04-15 - 3.2.0
+###Summary
+
+This is a feature and bugfix release in the Havana series.
+
+####Features
+- Add ability to configure any catalog driver
+
+####Bugfixes
+- Ensure log_file is absent when using syslog
+
+##2014-03-28 - 3.1.1
+###Summary
+
+This is a bugfix release in the Havana series.
+
+####Bugfixes
+- Fix inconsistent variable for mysql allowed hosts
+
+##2014-03-26 - 3.1.0
+###Summary
+
+This is a feature and bugfix release in the Havana series.
+
+####Features
+- Add ability to disable pki_setup
+- Add log_dir param, with option to disable
+- Add support to enable SSL
+
+####Bugfixes
+- Load tenant un-lazily if needed
+- Update endpoint argument
+- Remove setting of Keystone endpoint by default
+- Relax regex when keystone refuses connections
+
+##2014-01-16 - 3.0.0
+###Summary
+
+This is a backwards-incompatible major release for OpenStack Havana.
+
+####Backwards-incompatible changes
+- Move db_sync to its own class
+- Remove creation of Member role
+- Switch from signing/format to token/provider
+
+####Features
+- Create memcache_servers option to allow for multiple cache servers
+- Enable serving Keystone from Apache mod_wsgi
+- Improve performance of Keystone providers
+- Update endpoints to support paths and ssl
+- Add support for token expiration parameter
+
+####Bugfixes
+- Fix duplicated keystone endpoints
+- Refactor keystone_endpoint to use prefetch and flush paradigm
+
+##2013-10-07 - 2.2.0
+###Summary
+
+This is a feature and bugfix release in the Grizzly series.
+
+####Features
+- Optimized tenant and user queries
+- Added syslog support
+- Added support for token driver backend
+
+####Bugfixes
+- Various bug and lint fixes
+
+##2013-08-06 - 2.1.0
+###Summary
+
+This is a bugfix release in the Grizzly series.
+
+####Bugfixes
+- Fix allowed_hosts contitional statement
+- Select keystone endpoint based on SSL setting
+- Improve tenant_hash usage in keystone_tenant
+- Various cleanup and bug fixes
+
+####Maintenance
+- Pin dependencies
+
+##2013-06-18 - 2.0.0
+###Summary
+
+Initial release on StackForge.
+
+####Backwards-incompatible changes
+
+####Features
+- keystone_user can be used to change passwords
+- service tenant name now configurable
+- keystone_user is now idempotent
+
+####Bugfixes
+- Various cleanups and bug fixes
index e757d38fa873937bb122499c97db3809ecbcd2f4..23c74a880ccff9d588278e8919522bf6552755e0 100644 (file)
@@ -2,10 +2,24 @@ source 'https://rubygems.org'
 
 group :development, :test do
   gem 'puppetlabs_spec_helper', :require => false
-  gem 'puppet-lint', '~> 0.3.2'
+  gem 'rspec-puppet', '~> 2.1.0', :require => false
+
   gem 'metadata-json-lint'
-  gem 'rspec-puppet', '~> 1.0.1'
-  gem 'rake', '10.1.1'
+  gem 'puppet-lint-param-docs'
+  gem 'puppet-lint-absolute_classname-check'
+  gem 'puppet-lint-absolute_template_path'
+  gem 'puppet-lint-trailing_newline-check'
+
+  # Puppet 4.x related lint checks
+  gem 'puppet-lint-unquoted_string-check'
+  gem 'puppet-lint-leading_zero-check'
+  gem 'puppet-lint-variable_contains_upcase'
+  gem 'puppet-lint-numericvariable'
+
+  gem 'json'
+  gem 'webmock'
+  gem 'beaker-rspec', :require => false
+  gem 'beaker-puppet_install_helper', :require => false
 end
 
 if puppetversion = ENV['PUPPET_GEM_VERSION']
index 0bc44c17d29bdeea8c385279a6e258119c915707..88a11a0e7748b08d7c31023da75fe12e97a26806 100644 (file)
@@ -1,8 +1,4 @@
-Puppet Labs Keystone Module - Puppet module for managing Keystone
-
-Copyright (C) 2012 Puppet Labs Inc
-
-Puppet Labs can be contacted at: info@puppetlabs.com
+Copyright 2012 OpenStack Foundation
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
index 2f5b1555365f6bb6a65926f8101b9d01b0a8e53a..df6023740819a8353b436da13d0b7c912bb2adc3 100644 (file)
@@ -12,12 +12,11 @@ keystone
 5. [Limitations - OS compatibility, etc.](#limitations)
 6. [Development - Guide for contributing to the module](#development)
 7. [Contributors - Those with commits](#contributors)
-8. [Release Notes - Notes on the most recent updates to the module](#release-notes)
 
 Overview
 --------
 
-The keystone module is a part of [Stackforge](https://github.com/stackfoge), an effort by the Openstack infrastructure team to provide continuous integration testing and code review for Openstack and Openstack community projects not part of the core software.  The module its self is used to flexibly configure and manage the identify service for Openstack.
+The keystone module is a part of [OpenStack](https://github.com/openstack), an effort by the Openstack infrastructure team to provide continuous integration testing and code review for Openstack and Openstack community projects as part of the core software.  The module its self is used to flexibly configure and manage the identify service for Openstack.
 
 Module Description
 ------------------
@@ -45,10 +44,10 @@ To utilize the keystone module's functionality you will need to declare multiple
 
 ```puppet
 class { 'keystone':
-  verbose        => True,
-  catalog_type   => 'sql',
-  admin_token    => 'random_uuid',
-  sql_connection => 'mysql://keystone_admin:super_secret_db_password@openstack-controller.example.com/keystone',
+  verbose             => True,
+  catalog_type        => 'sql',
+  admin_token         => 'random_uuid',
+  database_connection => 'mysql://keystone_admin:super_secret_db_password@openstack-controller.example.com/keystone',
 }
 
 # Adds the admin credential to keystone.
@@ -59,10 +58,10 @@ class { 'keystone::roles::admin':
 
 # Installs the service user endpoint.
 class { 'keystone::endpoint':
-  public_address   => '10.16.0.101',
-  admin_address    => '10.16.1.101',
-  internal_address => '10.16.2.101',
-  region           => 'example-1',
+  public_url   => 'http://10.16.0.101:5000/v2.0',
+  admin_url    => 'http://10.16.1.101:35357/v2.0',
+  internal_url => 'http://10.16.2.101:5000/v2.0',
+  region       => 'example-1',
 }
 ```
 
@@ -148,6 +147,18 @@ Limitations
 
 * If you've setup Openstack using previous versions of this module you need to be aware that it used UUID as the dedault to the token_format parameter but now defaults to PKI.  If you're using this module to manage a Grizzly Openstack deployment that was set up using a development release of the modules or are attempting an upgrade from Folsom then you'll need to make sure you set the token_format to UUID at classification time.
 
+Beaker-Rspec
+------------
+
+This module has beaker-rspec tests
+
+To run:
+
+``shell
+bundle install
+bundle exec rspec spec/acceptance
+``
+
 Development
 -----------
 
@@ -158,150 +169,4 @@ Developer documentation for the entire puppet-openstack project.
 Contributors
 ------------
 
-* https://github.com/stackforge/puppet-keystone/graphs/contributors
-
-Release Notes
--------------
-
-**5.1.0**
-
-* Allow disabling or delaying the token_flush cron
-* crontab: ensure the script is run with shell
-* Use openstackclient for keystone_* providers
-* Add lib directories to $LOAD_PATH if not present
-* Remove keystone.rb provider for keystone_endpoint
-* Add timeout to API requests
-* Test keystone_user password with Net::HTTP
-* service_identity: add user/role ordering
-* Fix password check for SSL endpoints
-* add require json for to_json dependency
-* spec: pin rspec-puppet to 1.0.1
-* Switch to TLSv1
-* handle missing project/tenant when using ldap backend
-* Add support for LDAP connection pools
-* Sync keystone.py with upstream to function with Juno
-* Create resource cache upon creation
-* Implement caching lookup for keystone_user_role
-* Remove warnings from openstack responses
-* Properly handle embedded newlines in csv
-* support the ldap user_enabled_invert parameter
-* Shorten HTTP request timeout length
-* Tag packages with 'openstack'
-* Allow Keystone to be queried when using IPv6 ::0
-* Add ::keystone::policy class for policy management
-* New option replace_password for keystone_user
-* Pin puppetlabs-concat to 1.2.1 in fixtures
-* Set WSGI process display-name
-* Rename resource instance variable
-* Add native types for keystone paste configuration
-* Update .gitreview file for project rename
-
-**5.0.0**
-
-* Stable Juno release
-* Updated token driver, logging, and ldap config parameters for Juno
-* Changed admin_roles parameter to accept an array in order to configure multiple admin roles
-* Installs python-ldappool package for ldap
-* Added new parameters to keystone class to configure pki signing
-* Changed keystone class to inherit from keystone::params
-* Changed pki_setup to run regardless of token provider
-* Made UUID the default token provider
-* Made keystone_user_role idempotent
-* Added parameters to control whether to configure users
-* Stopped managing _member_ role since it is created automatically
-* Stopped overriding token_flush log file
-* Changed the usage of admin_endpoint to not include the API version
-* Allowed keystone_user_role to accept email as username
-* Added ability to set up keystone using Apache mod_wsgi
-* Migrated the keystone::db::mysql class to use openstacklib::db::mysql and deprecated the mysql_module parameter
-* Installs python-memcache when using token driver memcache
-* Enabled setting cert and key paths for PKI token signing
-* Added parameters for SSL communication between keystone and rabbitmq
-* Added parameter ignore_default_tenant to keystone::role::admin
-* Added parameter service_provider to keystone class
-* Added parameters for service validation to keystone class
-
-**4.2.0**
-
-* Added class for extended logging options
-* Fixed rabbit password leaking
-* Added parameters to set tenant descriptions
-* Fixed keystone user authorization error handling
-
-**4.1.0**
-
-* Added token flushing with cron.
-* Updated database api for consistency with other projects.
-* Fixed admin_token with secret parameter.
-* Fixed deprecated catalog driver.
-
-**4.0.0**
-
-* Stable Icehouse release.
-* Added template_file parameter to specify catalog.
-* Added keystone::config to handle additional custom options.
-* Added notification parameters.
-* Added support for puppetlabs-mysql 2.2 and greater.
-* Fixed deprecated sql section header in keystone.conf.
-* Fixed deprecated bind_host parameter.
-* Fixed example for native type keystone_service.
-* Fixed LDAP module bugs.
-* Fixed variable for host_access dependency.
-* Reduced default token duration to one hour.
-
-**3.2.0**
-
-* Added ability to configure any catalog driver.
-* Ensures log_file is absent when using syslog.
-
-**3.1.1**
-
-* Fixed inconsistent variable for mysql allowed hosts.
-
-**3.1.0**
-
-* Added ability to disable pki_setup.
-* Load tenant un-lazily if needed.
-* Add log_dir param, with option to disable.
-* Updated endpoint argument.
-* Added support to enable SSL.
-* Removes setting of Keystone endpoint by default.
-* Relaxed regex when keystone refuses connections.
-
-**3.0.0**
-
-* Major release for OpenStack Havana.
-* Fixed duplicated keystone endpoints.
-* Refactored keystone_endpoint to use prefetch and flush paradigm.
-* Switched from signing/format to token/provider.
-* Created memcache_servers option to allow for multiple cache servers.
-* Enabled serving Keystone from Apache mod_wsgi.
-* Moved db_sync to its own class.
-* Removed creation of Member role.
-* Improved performance of Keystone providers.
-* Updated endpoints to support paths and ssl.
-* Added support for token expiration parameter.
-
-**2.2.0**
-
-* Optimized tenant and user queries.
-* Added syslog support.
-* Added support for token driver backend.
-* Various bug and lint fixes.
-
-**2.1.0**
-
-* Tracks release of puppet-quantum
-* Fixed allowed_hosts contitional statement
-* Pinned depedencies
-* Select keystone endpoint based on SSL setting
-* Improved tenant_hash usage in keystone_tenant
-* Various cleanup and bug fixes.
-
-**2.0.0**
-
-* Upstream is now part of stackfoge.
-* keystone_user can be used to change passwords.
-* service tenant name now configurable.
-* keystone_user is now idempotent.
-* Various cleanups and bug fixes.
+* https://github.com/openstack/puppet-keystone/graphs/contributors
diff --git a/3rdparty/modules/keystone/checksums.json b/3rdparty/modules/keystone/checksums.json
deleted file mode 100644 (file)
index 7f46630..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-{
-  "Gemfile": "bda594bd6e3cc9ee1db4c29e55220505",
-  "LICENSE": "88c9def20bf88cdd1cf474cfb53f16ab",
-  "README.md": "d150d6dc30f3dd54b319317b681e1e14",
-  "Rakefile": "68e2a46cd546eeb34bab6dc1512b549d",
-  "examples/apache_dropin.pp": "c40c6fe26b4211c85fe2c55926d10bb2",
-  "examples/apache_with_paths.pp": "3113e40e01bb70b391b52b7e17509678",
-  "examples/ldap_full.pp": "284fd9fd95fc7091b924177a4e3f5c76",
-  "examples/ldap_identity.pp": "63f00b0a413163542e348d96a87c9f68",
-  "ext/keystone_test.rb": "d403c8c80616f94d0cac9ff12c327b9a",
-  "files/httpd/keystone.py": "a359685b85254d738c13b167c7e84e6b",
-  "lib/puppet/provider/keystone.rb": "c754d86f1ef111030c17b3690c063a6c",
-  "lib/puppet/provider/keystone_config/ini_setting.rb": "b3c3813be1c155f49fedf0a1178fe905",
-  "lib/puppet/provider/keystone_endpoint/openstack.rb": "1864e99269b8f707cb16dbf501bc5587",
-  "lib/puppet/provider/keystone_paste_ini/ini_setting.rb": "df7e671676104f090a07942f774844e3",
-  "lib/puppet/provider/keystone_role/openstack.rb": "54d3dda0ac3427bd1180df9190a5166f",
-  "lib/puppet/provider/keystone_service/openstack.rb": "279e16db49cf59734ef98ce6cbf581f8",
-  "lib/puppet/provider/keystone_tenant/openstack.rb": "9f443449581c23e54cd5bf0b1d62172a",
-  "lib/puppet/provider/keystone_user/openstack.rb": "032358692dae948d29d9464c97793f78",
-  "lib/puppet/provider/keystone_user_role/openstack.rb": "a9a3ba9b455c7cb6d630d7b6235ebd14",
-  "lib/puppet/provider/openstack.rb": "86e27a181394e3e8630c5a3934ba320b",
-  "lib/puppet/type/keystone_config.rb": "01069a89da581af00fed130fc373c2c3",
-  "lib/puppet/type/keystone_endpoint.rb": "78ee04053d0e8362b3d57eecd4dbb020",
-  "lib/puppet/type/keystone_paste_ini.rb": "5429630bad1a33ab3f14b45f403ed2af",
-  "lib/puppet/type/keystone_role.rb": "31a7dc4bdf4179b19f01021d03327e93",
-  "lib/puppet/type/keystone_service.rb": "f1ceb0d168964a4211fed962cf0ff156",
-  "lib/puppet/type/keystone_tenant.rb": "a7c8b678ceec538cdc22d6dfc9861e13",
-  "lib/puppet/type/keystone_user.rb": "f0ba9956b6631a7ae07b763fa2c9479c",
-  "lib/puppet/type/keystone_user_role.rb": "01e72389db896e4cf4a3ed8b15fb771c",
-  "lib/puppet/util/openstack.rb": "34cea508fb3cbd0cf2ac426004842c21",
-  "manifests/client.pp": "519836300977db1d5476112864d4782c",
-  "manifests/config.pp": "5e27a3b503cd4931e410a2d41d89fda1",
-  "manifests/cron/token_flush.pp": "4f2ce0209fbb9696eda2758ef84c18d2",
-  "manifests/db/mysql.pp": "c3cb8dc2e1e61392f00f0dc54ee0bc1b",
-  "manifests/db/postgresql.pp": "18cea325841979f63426633794157254",
-  "manifests/db/sync.pp": "3caf7ccd37b6f62714bf3b77d0dbf0f9",
-  "manifests/dev/install.pp": "49ce7909a859d2424cf1fbe5404eab0c",
-  "manifests/endpoint.pp": "da60281981160a38c5e3ca8bc744dca7",
-  "manifests/init.pp": "f9e76044c913474134eb7f58c60a7e7d",
-  "manifests/ldap.pp": "c49c737867f03d49f3fdff6ac46e9c51",
-  "manifests/logging.pp": "5774990dea77d17dfceaad4a8777824c",
-  "manifests/params.pp": "b2cbc2011a21fa630022a36d2975f946",
-  "manifests/policy.pp": "c8a8998316ea42f611a1c7ae6a563461",
-  "manifests/python.pp": "036cd9a1f400a6a150a1967dcb6f1427",
-  "manifests/resource/service_identity.pp": "cd6a8d9c451c6310c840149d50decf79",
-  "manifests/roles/admin.pp": "45b2a2826ff205a28ba30f7c63b0cf45",
-  "manifests/service.pp": "bae5e366e100ea38d9fd5c1885b0cf3b",
-  "manifests/wsgi/apache.pp": "b4215a0b8a59d4c39919b6f893820c97",
-  "metadata.json": "0995a4802848cf7cb6a90293f45aa3a5",
-  "spec/classes/keystone_client_spec.rb": "85457ed6327e795237afca58be906da6",
-  "spec/classes/keystone_cron_token_flush_spec.rb": "4648a3bba9210d5b7d51b9a6c8fff586",
-  "spec/classes/keystone_db_mysql_spec.rb": "6cb71468e5610210be2955305938dcfe",
-  "spec/classes/keystone_db_postgresql_spec.rb": "88f188cea91bd3bc7c46ecc7033e62df",
-  "spec/classes/keystone_endpoint_spec.rb": "581f77946576aaebce9df3b4dad6800e",
-  "spec/classes/keystone_ldap_spec.rb": "c25daffe970799d8619aa690c4c396bb",
-  "spec/classes/keystone_logging_spec.rb": "fe193b49405672cbf75e41b140d3f9b9",
-  "spec/classes/keystone_policy_spec.rb": "24dfcbd1e807015214c31d9e4a313619",
-  "spec/classes/keystone_python_spec.rb": "84f15d4d969b2cb7ab2d770d7ab0278f",
-  "spec/classes/keystone_roles_admin_spec.rb": "6b11c426e9dd91c7b766ef8c707ca129",
-  "spec/classes/keystone_service_spec.rb": "688f35435c12152a021ae39020296186",
-  "spec/classes/keystone_spec.rb": "14dfbd437ce31988a43332752b586c91",
-  "spec/classes/keystone_wsgi_apache_spec.rb": "5af4f3b9ee305f99df34753db9aa8fe1",
-  "spec/defines/keystone_resource_service_identity_spec.rb": "485bd7d1a7d189d88d4b86f5d50df8d0",
-  "spec/shared_examples.rb": "172c63c57efca8c741f297494ed9ef0f",
-  "spec/spec.opts": "a600ded995d948e393fbe2320ba8e51c",
-  "spec/spec_helper.rb": "c6521798536b607695fa32a60c8466aa",
-  "spec/unit/provider/keystone_endpoint/openstack_spec.rb": "8417a7da443c4cfe7c779536c07a2972",
-  "spec/unit/provider/keystone_paste_ini/ini_setting_spec.rb": "8b583280cfc7c67d64a2dfd8caa7a130",
-  "spec/unit/provider/keystone_role/openstack_spec.rb": "3dabd6528075e0f4496b10f4faf769b5",
-  "spec/unit/provider/keystone_service/openstack_spec.rb": "1badc29e61628e320509ce86e076e641",
-  "spec/unit/provider/keystone_spec.rb": "3eaa3720884b2c3096102b1cb37334cb",
-  "spec/unit/provider/keystone_tenant/openstack_spec.rb": "63ac277a61271577ecbcd5c729868cf2",
-  "spec/unit/provider/keystone_user/openstack_spec.rb": "0c68dda06669b26d9d1285196cfed0ec",
-  "spec/unit/provider/keystone_user_role/openstack_spec.rb": "d78aab324756f7183997b2f8300e9309",
-  "spec/unit/provider/openstack_spec.rb": "f06998179568513c4b83d19212d6427b",
-  "spec/unit/type/keystone_endpoint_spec.rb": "5dbd0b540a452bae36218b2a8794a41e",
-  "spec/unit/type/keystone_paste_ini_spec.rb": "9037113f96850d5567e9dc7c540915ae",
-  "spec/unit/type/keystone_user_role_spec.rb": "a03cfa9f55028d6a7f2a351582c1a93d",
-  "tests/site.pp": "0b2eb2ec36b10520aad1517b9a116e50"
-}
\ No newline at end of file
index 310f0a3fd6d21dcdb3cce3d569fbbe7c9e175ebe..5ed29264fe9a96725ac983d4a35558f2c2867954 100644 (file)
 
 Exec { logoutput => 'on_failure' }
 
-class { 'mysql::server': }
-class { 'keystone::db::mysql':
+class { '::mysql::server': }
+class { '::keystone::db::mysql':
   password => 'keystone',
 }
-class { 'keystone':
-  verbose        => true,
-  debug          => true,
-  sql_connection => 'mysql://keystone:keystone@127.0.0.1/keystone',
-  catalog_type   => 'sql',
-  admin_token    => 'admin_token',
-  enabled        => false,
+class { '::keystone':
+  verbose             => true,
+  debug               => true,
+  database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone',
+  catalog_type        => 'sql',
+  admin_token         => 'admin_token',
+  enabled             => false,
 }
-class { 'keystone::roles::admin':
+class { '::keystone::roles::admin':
   email    => 'test@puppetlabs.com',
   password => 'ChangeMe',
 }
-class { 'keystone::endpoint':
+class { '::keystone::endpoint':
   public_url => "https://${::fqdn}:5000/",
   admin_url  => "https://${::fqdn}:35357/",
 }
 
 keystone_config { 'ssl/enable': value => true }
 
-include apache
-class { 'keystone::wsgi::apache':
+include ::apache
+class { '::keystone::wsgi::apache':
   ssl => true
 }
index be28d395bc8bedbf9d7292abf4279b09d1b36cc6..8b0fc699c0cea900b3da641dd51377f5bd1e3b97 100644 (file)
 
 Exec { logoutput => 'on_failure' }
 
-class { 'mysql::server': }
-class { 'keystone::db::mysql':
+class { '::mysql::server': }
+class { '::keystone::db::mysql':
   password => 'keystone',
 }
-class { 'keystone':
-  verbose        => true,
-  debug          => true,
-  sql_connection => 'mysql://keystone_admin:keystone@127.0.0.1/keystone',
-  catalog_type   => 'sql',
-  admin_token    => 'admin_token',
-  enabled        => true,
+class { '::keystone':
+  verbose             => true,
+  debug               => true,
+  database_connection => 'mysql://keystone_admin:keystone@127.0.0.1/keystone',
+  catalog_type        => 'sql',
+  admin_token         => 'admin_token',
+  enabled             => true,
 }
-class { 'keystone::cron::token_flush': }
-class { 'keystone::roles::admin':
+class { '::keystone::cron::token_flush': }
+class { '::keystone::roles::admin':
   email    => 'test@puppetlabs.com',
   password => 'ChangeMe',
 }
-class { 'keystone::endpoint':
-  public_url    => "https://${::fqdn}:443/main/",
-  admin_address => "https://${::fqdn}:443/admin/",
+class { '::keystone::endpoint':
+  public_url => "https://${::fqdn}:443/main/",
+  admin_url  => "https://${::fqdn}:443/admin/",
 }
 
 keystone_config { 'ssl/enable': ensure  => absent }
 
-include apache
-class { 'keystone::wsgi::apache':
+include ::apache
+class { '::keystone::wsgi::apache':
   ssl         => true,
   public_port => 443,
   admin_port  => 443,
index bc455690f43cff5141c77becd1808edff9aceaae..09ce7c8eff21252030d4eaab0a7e0fb24fa87543 100644 (file)
@@ -3,7 +3,7 @@
 
 # Ensure this matches what is in LDAP or keystone will try to recreate
 # the admin user
-class { 'keystone::roles::admin':
+class { '::keystone::roles::admin':
   email    => 'test@example.com',
   password => 'ChangeMe',
 }
@@ -15,58 +15,58 @@ class { 'keystone::roles::admin':
 # ldapsearch -v -x -H 'ldap://example.com:389' -D \
 # "uid=bind,cn=users,cn=accounts,dc=example,dc=com" -w SecretPass \
 # -b cn=users,cn=accounts,dc=example,dc=com
-class { 'keystone:ldap':
-  url                         => 'ldap://ldap.example.com:389',
-  user                        => 'uid=bind,cn=users,cn=accounts,dc=example,dc=com',
-  password                    => 'SecretPass',
-  suffix                      => 'dc=example,dc=com',
-  query_scope                 => 'sub',
-  user_tree_dn                => 'cn=users,cn=accounts,dc=example,dc=com',
-  user_id_attribute           => 'uid',
-  user_name_attribute         => 'uid',
-  user_mail_attribute         => 'mail',
-  user_allow_create           => 'False',
-  user_allow_update           => 'False',
-  user_allow_delete           => 'False',
-  user_enabled_emulation      => 'True',
-  user_enabled_emulation_dn   => 'cn=openstack-enabled,cn=groups,cn=accounts,dc=example,dc=com',
-  group_tree_dn               => 'ou=groups,ou=openstack,dc=example,dc=com',
-  group_objectclass           => 'organizationalRole',
-  group_id_attribute          => 'cn',
-  group_name_attribute        => 'cn',
-  group_member_attribute      => 'RoleOccupant',
-  group_desc_attribute        => 'description',
-  group_allow_create          => 'True',
-  group_allow_update          => 'True',
-  group_allow_delete          => 'True',
-  project_tree_dn             => 'ou=projects,ou=openstack,dc=example,dc=com',
-  project_objectclass         => 'organizationalUnit',
-  project_id_attribute        => 'ou',
-  project_member_attribute    => 'member',
-  project_name_attribute      => 'ou',
-  project_desc_attribute      => 'description',
-  project_allow_create        => 'True',
-  project_allow_update        => 'True',
-  project_allow_delete        => 'True',
-  project_enabled_emulation   => 'True',
-  project_enabled_emulation_dn=> 'cn=enabled,ou=openstack,dc=example,dc=com',
-  role_tree_dn                => 'ou=roles,ou=openstack,dc=example,dc=com',
-  role_objectclass            => 'organizationalRole',
-  role_id_attribute           => 'cn',
-  role_name_attribute         => 'cn',
-  role_member_attribute       => 'roleOccupant',
-  role_allow_create           => 'True',
-  role_allow_update           => 'True',
-  role_allow_delete           => 'True',
-  identity_driver             => 'keystone.identity.backends.ldap.Identity',
-  assignment_driver           => 'keystone.assignment.backends.ldap.Assignment',
-  use_tls                     => 'True',
-  tls_cacertfile              => '/etc/ssl/certs/ca-certificates.crt',
-  tls_req_cert                => 'demand',
-  use_pool                    => 'True',
-  use_auth_pool               => 'True',
-  pool_size                   => 5,
-  auth_pool_size              => 5,
-  pool_retry_max              => 3,
-  pool_connection_timeout     => 120,
+class { '::keystone:ldap':
+  url                          => 'ldap://ldap.example.com:389',
+  user                         => 'uid=bind,cn=users,cn=accounts,dc=example,dc=com',
+  password                     => 'SecretPass',
+  suffix                       => 'dc=example,dc=com',
+  query_scope                  => 'sub',
+  user_tree_dn                 => 'cn=users,cn=accounts,dc=example,dc=com',
+  user_id_attribute            => 'uid',
+  user_name_attribute          => 'uid',
+  user_mail_attribute          => 'mail',
+  user_allow_create            => 'False',
+  user_allow_update            => 'False',
+  user_allow_delete            => 'False',
+  user_enabled_emulation       => 'True',
+  user_enabled_emulation_dn    => 'cn=openstack-enabled,cn=groups,cn=accounts,dc=example,dc=com',
+  group_tree_dn                => 'ou=groups,ou=openstack,dc=example,dc=com',
+  group_objectclass            => 'organizationalRole',
+  group_id_attribute           => 'cn',
+  group_name_attribute         => 'cn',
+  group_member_attribute       => 'RoleOccupant',
+  group_desc_attribute         => 'description',
+  group_allow_create           => 'True',
+  group_allow_update           => 'True',
+  group_allow_delete           => 'True',
+  project_tree_dn              => 'ou=projects,ou=openstack,dc=example,dc=com',
+  project_objectclass          => 'organizationalUnit',
+  project_id_attribute         => 'ou',
+  project_member_attribute     => 'member',
+  project_name_attribute       => 'ou',
+  project_desc_attribute       => 'description',
+  project_allow_create         => 'True',
+  project_allow_update         => 'True',
+  project_allow_delete         => 'True',
+  project_enabled_emulation    => 'True',
+  project_enabled_emulation_dn => 'cn=enabled,ou=openstack,dc=example,dc=com',
+  role_tree_dn                 => 'ou=roles,ou=openstack,dc=example,dc=com',
+  role_objectclass             => 'organizationalRole',
+  role_id_attribute            => 'cn',
+  role_name_attribute          => 'cn',
+  role_member_attribute        => 'roleOccupant',
+  role_allow_create            => 'True',
+  role_allow_update            => 'True',
+  role_allow_delete            => 'True',
+  identity_driver              => 'keystone.identity.backends.ldap.Identity',
+  assignment_driver            => 'keystone.assignment.backends.ldap.Assignment',
+  use_tls                      => 'True',
+  tls_cacertfile               => '/etc/ssl/certs/ca-certificates.crt',
+  tls_req_cert                 => 'demand',
+  use_pool                     => 'True',
+  use_auth_pool                => 'True',
+  pool_size                    => 5,
+  auth_pool_size               => 5,
+  pool_retry_max               => 3,
+  pool_connection_timeout      => 120,
 }
index 41272c52f1485fae3ecfa6152e57bddafadeab4d..f3a578cae246ca7ccf730aa8632f57dc781beaab 100644 (file)
@@ -3,7 +3,7 @@
 
 # Ensure this matches what is in LDAP or keystone will try to recreate
 # the admin user
-class { 'keystone::roles::admin':
+class { '::keystone::roles::admin':
   email    => 'test@example.com',
   password => 'ChangeMe',
 }
@@ -11,18 +11,18 @@ class { 'keystone::roles::admin':
 # You can test this connection with ldapsearch first to ensure it works.
 # This was tested against a FreeIPA box, you will likely need to change the
 # attributes to match your configuration.
-class { 'keystone:ldap':
-  identity_driver       => 'keystone.identity.backends.ldap.Identity',
-  url                   => 'ldap://ldap.example.com:389',
-  user                  => 'uid=bind,cn=users,cn=accounts,dc=example,dc=com',
-  password              => 'SecretPass',
-  suffix                => 'dc=example,dc=com',
-  query_scope           => 'sub',
-  user_tree_dn          => 'cn=users,cn=accounts,dc=example,dc=com',
-  user_id_attribute     => 'uid',
-  user_name_attribute   => 'uid',
-  user_mail_attribute   => 'mail',
-  user_allow_create     => 'False',
-  user_allow_update     => 'False',
-  user_allow_delete     => 'False'
+class { '::keystone:ldap':
+  identity_driver     => 'keystone.identity.backends.ldap.Identity',
+  url                 => 'ldap://ldap.example.com:389',
+  user                => 'uid=bind,cn=users,cn=accounts,dc=example,dc=com',
+  password            => 'SecretPass',
+  suffix              => 'dc=example,dc=com',
+  query_scope         => 'sub',
+  user_tree_dn        => 'cn=users,cn=accounts,dc=example,dc=com',
+  user_id_attribute   => 'uid',
+  user_name_attribute => 'uid',
+  user_mail_attribute => 'mail',
+  user_allow_create   => 'False',
+  user_allow_update   => 'False',
+  user_allow_delete   => 'False'
 }
index f5ce498c5152390bd084da88b0962fec2d39ce18..81c5348a35f649521fe0b1451fbb6ba142d9796b 100644 (file)
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import logging
-import os
-
-from oslo import i18n
-
-
-# NOTE(dstanek): i18n.enable_lazy() must be called before
-# keystone.i18n._() is called to ensure it has the desired lazy lookup
-# behavior. This includes cases, like keystone.exceptions, where
-# keystone.i18n._() is called at import time.
-i18n.enable_lazy()
-
-
-from keystone import backends
-from keystone.common import dependency
-from keystone.common import environment
-from keystone.common import sql
-from keystone import config
-from keystone.openstack.common import log
-from keystone import service
-
+#
+# This file was copied from https://github.com/openstack/keystone/raw/a4f29db2b8cde1b445b86218fb5543295da2092c/httpd/keystone.py
+# It's only required for platforms on which it is not packaged yet.
+# It should be removed when available everywhere in a package.
+#
 
-CONF = config.CONF
+import os
 
-config.configure()
-sql.initialize()
-config.set_default_for_default_log_levels()
+from keystone.server import wsgi as wsgi_server
 
-CONF(project='keystone')
-config.setup_logging()
 
-environment.use_stdlib()
 name = os.path.basename(__file__)
 
-if CONF.debug:
-    CONF.log_opt_values(log.getLogger(CONF.prog), logging.DEBUG)
-
-
-drivers = backends.load_backends()
-
 # NOTE(ldbragst): 'application' is required in this context by WSGI spec.
 # The following is a reference to Python Paste Deploy documentation
 # http://pythonpaste.org/deploy/
-application = service.loadapp('config:%s' % config.find_paste_config(), name)
-
-dependency.resolve_future_dependencies()
+application = wsgi_server.initialize_application(name)
index b398a8e308148ce9585af207310757c36a1b3f7a..4e7815abf75f3c595201620fb3affc219740541c 100644 (file)
@@ -1,36 +1,33 @@
 require 'puppet/util/inifile'
 require 'puppet/provider/openstack'
+require 'puppet/provider/openstack/auth'
+require 'puppet/provider/openstack/credentials'
+
 class Puppet::Provider::Keystone < Puppet::Provider::Openstack
 
-  def request(service, action, object, credentials, *properties)
-    begin
-      super
-    rescue Puppet::Error::OpenstackAuthInputError => error
-      keystone_request(service, action, object, credentials, error, *properties)
-    end
-  end
+  extend Puppet::Provider::Openstack::Auth
 
-  def self.request(service, action, object, credentials, *properties)
-    begin
-      super
-    rescue Puppet::Error::OpenstackAuthInputError => error
-      keystone_request(service, action, object, credentials, error, *properties)
-    end
-  end
+  INI_FILENAME = '/etc/keystone/keystone.conf'
 
-  def keystone_request(service, action, object, credentials, error, *properties)
-    self.class.keystone_request(service, action, object, credentials, error, *properties)
+  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.keystone_request(service, action, object, credentials, error, *properties)
-    credentials = {
-      'token'    => get_admin_token,
-      'auth_url' => get_admin_endpoint,
-    }
-    raise error unless (credentials['token'] && credentials['auth_url'])
-    auth_args = token_auth_args(credentials)
-    args = [object, properties, auth_args].flatten.compact
-    authenticate_request(service, action, args)
+  def self.admin_endpoint
+    @admin_endpoint ||= get_admin_endpoint
   end
 
   def self.admin_token
@@ -45,21 +42,12 @@ class Puppet::Provider::Keystone < Puppet::Provider::Openstack
     end
   end
 
-  def self.admin_endpoint
-    @admin_endpoint ||= get_admin_endpoint
-  end
-
-  def get_admin_token
-    self.class.get_admin_token
-  end
-
-
   def self.get_admin_endpoint
     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}/v2.0/"
+          return "#{auth_url}/v#{@credentials.version}/"
         end
 
         if keystone_file['DEFAULT']['admin_port']
@@ -87,22 +75,34 @@ class Puppet::Provider::Keystone < Puppet::Provider::Openstack
       end
     end
 
-    "#{protocol}://#{host}:#{admin_port}/v2.0/"
+    "#{protocol}://#{host}:#{admin_port}/v#{@credentials.version}/"
   end
 
-  def get_admin_endpoint
-    self.class.get_admin_endpoint
+  def self.request(service, action, properties=nil)
+    super
+    rescue Puppet::Error::OpenstackAuthInputError => error
+      request_by_service_token(service, action, error, properties)
   end
 
-  def self.keystone_file
-    return @keystone_file if @keystone_file
-    @keystone_file = Puppet::Util::IniConfig::File.new
-    @keystone_file.read('/etc/keystone/keystone.conf')
-    @keystone_file
+  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
 
-  def keystone_file
-    self.class.keystone_file
+  def self.ini_filename
+    INI_FILENAME
+  end
+
+  def self.keystone_file
+    return @keystone_file if @keystone_file
+    if File.exists?(ini_filename)
+      @keystone_file = Puppet::Util::IniConfig::File.new
+      @keystone_file.read(ini_filename)
+      @keystone_file
+    end
   end
 
   # Helper functions to use on the pre-validated enabled field
@@ -113,5 +113,4 @@ class Puppet::Provider::Keystone < Puppet::Provider::Openstack
   def sym_to_bool(sym)
     sym == :true ? true : false
   end
-
 end
index ac7780d483f56f2dbd0da66b73b0f2c4a1c8748d..97de693d86853f48639f65f9c2ff99db67e05442 100644 (file)
@@ -7,6 +7,8 @@ Puppet::Type.type(:keystone_endpoint).provide(
 
   desc "Provider to manage keystone endpoints."
 
+  @credentials = Puppet::Provider::Openstack::CredentialsV2_0.new
+
   def initialize(value={})
     super(value)
     @property_flush = {}
@@ -16,6 +18,7 @@ Puppet::Type.type(:keystone_endpoint).provide(
     properties = []
     # The region property is just ignored. We should fix this in kilo.
     region, name = resource[:name].split('/')
+    properties << name
     properties << '--region'
     properties << region
     if resource[:public_url]
@@ -30,56 +33,53 @@ Puppet::Type.type(:keystone_endpoint).provide(
       properties << '--adminurl'
       properties << resource[:admin_url]
     end
-    @instance = request('endpoint', 'create', name, resource[:auth], properties)
-  end
-
-  def exists?
-    ! instance(resource[:name]).empty?
+     self.class.request('endpoint', 'create', properties)
+     @property_hash[:ensure] = :present
   end
 
   def destroy
-    id = instance(resource[:name])[:id]
-    request('endpoint', 'delete', id, resource[:auth])
+    self.class.request('endpoint', 'delete', @property_hash[:id])
+    @property_hash.clear
   end
 
+  def exists?
+    @property_hash[:ensure] == :present
+  end
 
   def region
-    instance(resource[:name])[:region]
+    @property_hash[:region]
   end
 
-
   def public_url=(value)
     @property_flush[:public_url] = value
   end
 
   def public_url
-    instance(resource[:name])[:public_url]
+    @property_hash[:public_url]
   end
 
-
   def internal_url=(value)
     @property_flush[:internal_url] = value
   end
 
   def internal_url
-    instance(resource[:name])[:internal_url]
+    @property_hash[:internal_url]
   end
 
-
   def admin_url=(value)
     @property_flush[:admin_url] = value
   end
 
   def admin_url
-    instance(resource[:name])[:admin_url]
+    @property_hash[:admin_url]
   end
 
   def id
-    instance(resource[:name])[:id]
+    @property_hash[:id]
   end
 
   def self.instances
-    list = request('endpoint', 'list', nil, nil, '--long')
+    list = request('endpoint', 'list', '--long')
     list.collect do |endpoint|
       new(
         :name         => "#{endpoint[:region]}/#{endpoint[:service_name]}",
@@ -93,30 +93,20 @@ Puppet::Type.type(:keystone_endpoint).provide(
     end
   end
 
-  def instances
-    instances = request('endpoint', 'list', nil, resource[:auth], '--long')
-    instances.collect do |endpoint|
-      {
-        :name         => "#{endpoint[:region]}/#{endpoint[:service_name]}",
-        :id           => endpoint[:id],
-        :region       => endpoint[:region],
-        :public_url   => endpoint[:publicurl],
-        :internal_url => endpoint[:internalurl],
-        :admin_url    => endpoint[:adminurl]
-      }
+  def self.prefetch(resources)
+    endpoints = instances
+    resources.keys.each do |name|
+       if provider = endpoints.find{ |endpoint| endpoint.name == name }
+        resources[name].provider = provider
+      end
     end
   end
 
-  def instance(name)
-    @instance ||= instances.select { |instance| instance[:name] == name }.first || {}
-  end
-
   def flush
-    if  ! @property_flush.empty?
+    if ! @property_flush.empty?
       destroy
       create
       @property_flush.clear
     end
   end
-
 end
index b3bd856217c237a276fd8e710b0a3ec87977a59b..b15462047d4c0626a9d5ad33c4c8fd00134abf69 100644 (file)
@@ -7,25 +7,33 @@ Puppet::Type.type(:keystone_role).provide(
 
   desc 'Provider for keystone roles.'
 
-  def create
-    properties = []
-    @instance = request('role', 'create', resource[:name], resource[:auth], properties)
+  @credentials = Puppet::Provider::Openstack::CredentialsV2_0.new
+
+  def initialize(value={})
+    super(value)
+    @property_flush = {}
   end
 
-  def exists?
-    ! instance(resource[:name]).empty?
+  def create
+    self.class.request('role', 'create', name)
+    @property_hash[:ensure] = :present
   end
 
   def destroy
-    request('role', 'delete', resource[:name], resource[:auth])
+    self.class.request('role', 'delete', @property_hash[:id])
+    @property_hash.clear
+  end
+
+  def exists?
+    @property_hash[:ensure] == :present
   end
 
   def id
-    instance(resource[:name])[:id]
+    @property_hash[:id]
   end
 
   def self.instances
-    list = request('role', 'list', nil, nil)
+    list = request('role', 'list')
     list.collect do |role|
       new(
         :name        => role[:name],
@@ -35,18 +43,12 @@ Puppet::Type.type(:keystone_role).provide(
     end
   end
 
-  def instances
-    instances = request('role', 'list', nil, resource[:auth])
-    instances.collect do |role|
-      {
-        :name        => role[:name],
-        :id          => role[:id]
-      }
+  def self.prefetch(resources)
+    roles = instances
+    resources.keys.each do |name|
+       if provider = roles.find{ |role| role.name == name }
+        resources[name].provider = provider
+      end
     end
   end
-
-  def instance(name)
-    @instance ||= instances.select { |instance| instance[:name] == name }.first || {}
-  end
-
 end
index 54e75f5963504e21af9168e99886766894cc9432..40aa8e2feaf80fab0fe75dd207b7a195ee8713d6 100644 (file)
@@ -7,6 +7,8 @@ Puppet::Type.type(:keystone_service).provide(
 
   desc "Provider to manage keystone services."
 
+  @credentials = Puppet::Provider::Openstack::CredentialsV2_0.new
+
   def initialize(value={})
     super(value)
     @property_flush = {}
@@ -18,46 +20,45 @@ Puppet::Type.type(:keystone_service).provide(
       properties << '--description'
       properties << resource[:description]
     end
-    if resource[:type]
-      properties << '--type'
-      properties << resource[:type]
-    end
-    @instance = request('service', 'create', resource[:name], resource[:auth], properties)
+    raise(Puppet::Error, 'The service type is mandatory') unless resource[:type]
+    properties << '--type'
+    properties << resource[:type]
+    properties << resource[:name]
+    self.class.request('service', 'create', properties)
+    @property_hash[:ensure] = :present
   end
 
   def exists?
-    ! instance(resource[:name]).empty?
+    @property_hash[:ensure] == :present
   end
 
   def destroy
-    request('service', 'delete', resource[:name], resource[:auth])
+    self.class.request('service', 'delete', @property_hash[:id])
+    @property_hash.clear
   end
 
-
   def description=(value)
-    raise(Puppet::Error, "Updating the service is not currently supported.")
+    @property_flush[:description] = value
   end
 
   def description
-    instance(resource[:name])[:description]
+    @property_hash[:description]
   end
 
-
   def type=(value)
-    raise(Puppet::Error, "Updating the service is not currently supported.")
+    @property_flush[:type] = value
   end
 
   def type
-    instance(resource[:name])[:type]
+    @property_hash[:type]
   end
 
-
   def id
-    instance(resource[:name])[:id]
+    @property_hash[:id]
   end
 
   def self.instances
-    list = request('service', 'list', nil, nil, '--long')
+    list = request('service', 'list', '--long')
     list.collect do |service|
       new(
         :name        => service[:name],
@@ -69,30 +70,20 @@ Puppet::Type.type(:keystone_service).provide(
     end
   end
 
-  def instances
-    instances = request('service', 'list', nil, resource[:auth], '--long')
-    instances.collect do |service|
-      {
-        :name        => service[:name],
-        :type        => service[:type],
-        :description => service[:description],
-        :id          => service[:id]
-      }
+  def self.prefetch(resources)
+    services = instances
+    resources.keys.each do |name|
+       if provider = services.find{ |service| service.name == name }
+        resources[name].provider = provider
+      end
     end
   end
 
-  def instance(name)
-    @instance ||= instances.select { |instance| instance[:name] == name }.first || {}
-  end
-
   def flush
-    options = []
-    if @property_flush
-      # There is a --description flag for the set command, but it does not work if the value is empty
-      (options << '--property' << "type=#{resource[:type]}") if @property_flush[:type]
-      (options << '--property' << "description=#{resource[:description]}") if @property_flush[:description]
-      request('project', 'set', resource[:name], resource[:auth], options) unless options.empty?
+    if ! @property_flush.empty?
+      destroy
+      create
+      @property_flush.clear
     end
   end
-
 end
index 7d19fcef0a8dcffe74e2f865ce2af1f957c2b755..198798477d9f0422b62ff65088fc52b0c1ded287 100644 (file)
@@ -7,13 +7,15 @@ Puppet::Type.type(:keystone_tenant).provide(
 
   desc "Provider to manage keystone tenants/projects."
 
+  @credentials = Puppet::Provider::Openstack::CredentialsV2_0.new
+
   def initialize(value={})
     super(value)
     @property_flush = {}
   end
 
   def create
-    properties = []
+    properties = [resource[:name]]
     if resource[:enabled] == :true
       properties << '--enable'
     elsif resource[:enabled] == :false
@@ -23,42 +25,41 @@ Puppet::Type.type(:keystone_tenant).provide(
       properties << '--description'
       properties << resource[:description]
     end
-    @instance = request('project', 'create', resource[:name], resource[:auth], properties)
+     self.class.request('project', 'create', properties)
+     @property_hash[:ensure] = :present
   end
 
   def exists?
-    ! instance(resource[:name]).empty?
+    @property_hash[:ensure] == :present
   end
 
   def destroy
-    request('project', 'delete', resource[:name], resource[:auth])
+    self.class.request('project', 'delete', @property_hash[:id])
+    @property_hash.clear
   end
 
-
   def enabled=(value)
     @property_flush[:enabled] = value
   end
 
   def enabled
-    bool_to_sym(instance(resource[:name])[:enabled])
+    bool_to_sym(@property_hash[:enabled])
   end
 
-
   def description=(value)
     @property_flush[:description] = value
   end
 
   def description
-    instance(resource[:name])[:description]
+    @property_hash[:description]
   end
 
-
   def id
-    instance(resource[:name])[:id]
+    @property_hash[:id]
   end
 
   def self.instances
-    list = request('project', 'list', nil, nil, '--long')
+    list = request('project', 'list', '--long')
     list.collect do |project|
       new(
         :name        => project[:name],
@@ -70,30 +71,28 @@ Puppet::Type.type(:keystone_tenant).provide(
     end
   end
 
-  def instances
-    instances = request('project', 'list', nil, resource[:auth], '--long')
-    instances.collect do |project|
-      {
-        :name        => project[:name],
-        :enabled     => project[:enabled].downcase.chomp == 'true' ? true : false,
-        :description => project[:description],
-        :id          => project[:id]
-      }
+  def self.prefetch(resources)
+    tenants = instances
+    resources.keys.each do |name|
+       if provider = tenants.find{ |tenant| tenant.name == name }
+        resources[name].provider = provider
+      end
     end
   end
 
-  def instance(name)
-    @instance ||= instances.select { |instance| instance[:name] == name }.first || {}
-  end
-
   def flush
     options = []
-    if @property_flush
-      (options << '--enable') if @property_flush[:enabled] == :true
-      (options << '--disable') if @property_flush[:enabled] == :false
-      # There is a --description flag for the set command, but it does not work if the value is empty
-      (options << '--property' << "description=#{resource[:description]}") if @property_flush[:description]
-      request('project', 'set', resource[:name], resource[:auth], options) unless options.empty?
+    if @property_flush && !@property_flush.empty?
+      case @property_flush[:enabled]
+      when :true
+        options << '--enable'
+      when :false
+        options << '--disable'
+      end
+      (options << "--description=#{resource[:description]}") if @property_flush[:description]
+      options << @property_hash[:id]
+      self.class.request('project', 'set', options) unless options.empty?
+      @property_flush.clear
     end
   end
 
index 6c8d04aa292f7d9bee447cba712986590921abd2..98a34cd3cd05a8d5ab4a5f506ebe2de4348a3c6b 100644 (file)
@@ -1,6 +1,5 @@
-require 'net/http'
-require 'json'
 require 'puppet/provider/keystone'
+
 Puppet::Type.type(:keystone_user).provide(
   :openstack,
   :parent => Puppet::Provider::Keystone
@@ -8,137 +7,120 @@ Puppet::Type.type(:keystone_user).provide(
 
   desc "Provider to manage keystone users."
 
+  @credentials = Puppet::Provider::Openstack::CredentialsV2_0.new
+
   def initialize(value={})
     super(value)
     @property_flush = {}
   end
 
   def create
-    properties = []
+    properties = [resource[:name]]
     if resource[:enabled] == :true
       properties << '--enable'
     elsif resource[:enabled] == :false
       properties << '--disable'
     end
     if resource[:password]
-      properties << '--password'
-      properties << resource[:password]
+      properties << '--password' << resource[:password]
     end
     if resource[:tenant]
-      properties << '--project'
-      properties << resource[:tenant]
+      properties << '--project' << resource[:tenant]
     end
     if resource[:email]
-      properties << '--email'
-      properties << resource[:email]
+      properties << '--email' << resource[:email]
     end
-    @instance = request('user', 'create', resource[:name], resource[:auth], properties)
+    self.class.request('user', 'create', properties)
+    @property_hash[:ensure] = :present
   end
 
-  def exists?
-    ! instance(resource[:name]).empty?
+  def destroy
+    self.class.request('user', 'delete', @property_hash[:id])
+    @property_hash.clear
   end
 
-  def destroy
-    request('user', 'delete', resource[:name], resource[:auth])
+  def flush
+    options = []
+    if @property_flush && !@property_flush.empty?
+      options << '--enable'  if @property_flush[:enabled] == :true
+      options << '--disable' if @property_flush[:enabled] == :false
+      # There is a --description flag for the set command, but it does not work if the value is empty
+      options << '--password' << resource[:password] if @property_flush[:password]
+      options << '--email'    << resource[:email]    if @property_flush[:email]
+      # project handled in tenant= separately
+      unless options.empty?
+        options << @property_hash[:id]
+        self.class.request('user', 'set', options)
+      end
+      @property_flush.clear
+    end
   end
 
+  def exists?
+    @property_hash[:ensure] == :present
+  end
+
+  # Types properties
+  def enabled
+    bool_to_sym(@property_hash[:enabled])
+  end
 
   def enabled=(value)
     @property_flush[:enabled] = value
   end
 
-  def enabled
-    bool_to_sym(instance(resource[:name])[:enabled])
+  def email
+    @property_hash[:email]
   end
 
+  def email=(value)
+    @property_flush[:email] = value
+  end
 
-  def password=(value)
-    @property_flush[:password] = value
+  def id
+    @property_hash[:id]
   end
 
   def password
-    # if we don't know a password we can't test it
-    return nil if resource[:password] == nil
-    # if the user is disabled then the password can't be changed
-    return resource[:password] if resource[:enabled] == :false
-    # if replacing password is disabled, then don't change it
-    return resource[:password] if resource[:replace_password] == :false
-    # we can't get the value of the password but we can test to see if the one we know
-    # about works, if it doesn't then return nil, causing it to be reset
-    endpoint = nil
-    if password_credentials_set?(resource[:auth]) || service_credentials_set?(resource[:auth])
-      endpoint = (resource[:auth])['auth_url']
-    elsif openrc_set?(resource[:auth])
-      endpoint = get_credentials_from_openrc(resource[:auth])['auth_url']
-    elsif env_vars_set?
-      endpoint = ENV['OS_AUTH_URL']
-    else
-      # try to get endpoint from keystone.conf
-      endpoint = get_admin_endpoint
-    end
-    if endpoint == nil
-      raise(Puppet::Error::OpenstackAuthInputError, 'Could not find auth url to check user password.')
+    res = nil
+    return res if resource[:password] == nil
+    if resource[:enabled] == :false || resource[:replace_password] == :false
+      # Unchanged password
+      res = resource[:password]
     else
-      auth_params = {
-        'username'    => resource[:name],
-        'password'    => resource[:password],
-        'tenant_name' => resource[:tenant],
-        'auth_url'    => endpoint,
-      }
-      # LP#1408754
-      # Ideally this would be checked with the `openstack token issue` command,
-      # but that command is not available with version 0.3.0 of openstackclient
-      # which is what ships on Ubuntu during Juno.
-      # Instead we'll check whether the user can authenticate with curl.
-      creds_hash = {
-        :auth => {
-          :passwordCredentials => {
-            :username => auth_params['username'],
-            :password => auth_params['password'],
-          }
-        }
-      }
-      url = URI.parse(endpoint)
-      # 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
-      http = Net::HTTP.start(url.hostname, url.port, {:use_ssl => use_ssl})
-      request = Net::HTTP::Post.new('/v2.0/tokens')
-      request.body = creds_hash.to_json
-      request.content_type = 'application/json'
-      response = http.request(request)
-      if response.code.to_i == 401 || response.code.to_i == 403 # 401 => unauthorized, 403 => userDisabled
-        return nil
-      elsif ! (response.code == 200 || response.code == 203)
-        return resource[:password]
+      # 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]
+      begin
+        token = Puppet::Provider::Openstack.request('token', 'issue', ['--format', 'value'], credentials)
+      rescue Puppet::Error::OpenstackUnauthorizedError
+        # password is invalid
       else
-        raise(Puppet::Error, "Received bad response while trying to authenticate user: #{response.body}")
+        res = resource[:password] unless token.empty?
       end
     end
+    return res
   end
 
-  def tenant=(value)
-    begin
-      request('user', 'set', resource[:name], resource[:auth], '--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
-    end
-    set_project(value)
+  def password=(value)
+    @property_flush[:password] = value
+  end
+
+  def replace_password
+    @property_hash[:replace_password]
+  end
+
+  def replace_password=(value)
+    @property_flush[:replace_password] = value
   end
 
   def tenant
     return resource[:tenant] if sym_to_bool(resource[:ignore_default_tenant])
     # use the one returned from instances
-    tenant_name = instance(resource[:name])[:project]
+    tenant_name = @property_hash[:project]
     if tenant_name.nil? or tenant_name.empty?
       # if none (i.e. ldap backend) use the given one
       tenant_name = resource[:tenant]
@@ -151,7 +133,7 @@ Puppet::Type.type(:keystone_user).provide(
     # 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 = request('user role', 'list', resource[:name], resource[:auth], ['--project', tenant_name])
+    roles = self.class.request('user role', 'list', [resource[:name], '--project', tenant_name])
     if roles.empty?
       return nil
     else
@@ -159,64 +141,48 @@ Puppet::Type.type(:keystone_user).provide(
     end
   end
 
-  def replace_password
-    instance(resource[:name])[:replace_password]
-  end
-
-  def replace_password=(value)
-    @property_flush[:replace_password] = value
-  end
-
-  def email=(value)
-    @property_flush[:email] = value
-  end
-
-  def email
-    instance(resource[:name])[:email]
-  end
-
-  def id
-    instance(resource[:name])[:id]
+  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])
   end
 
   def self.instances
-    list = request('user', 'list', nil, nil, '--long')
+    list = request('user', 'list', '--long')
     list.collect do |user|
       new(
         :name        => user[:name],
         :ensure      => :present,
         :enabled     => user[:enabled].downcase.chomp == 'true' ? true : false,
         :password    => user[:password],
-        :tenant      => user[:project],
+        :project     => user[:project],
         :email       => user[:email],
         :id          => user[:id]
       )
     end
   end
 
-  def instances
-    instances = request('user', 'list', nil, resource[:auth], '--long')
-    instances.collect do |user|
-      {
-        :name        => user[:name],
-        :enabled     => user[:enabled].downcase.chomp == 'true' ? true : false,
-        :password    => user[:password],
-        :project     => user[:project],
-        :email       => user[:email],
-        :id          => user[:id]
-      }
+  def self.prefetch(resources)
+    users = instances
+    resources.keys.each do |name|
+       if provider = users.find{ |user| user.name == name }
+        resources[name].provider = provider
+      end
     end
   end
 
-  def instance(name)
-    @instance ||= instances.select { |instance| instance[:name] == name }.first || {}
-  end
-
-  def set_project(newproject)
+  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', resource[:name], resource[:auth], ['--project', newproject])
+    roles = request('user role', 'list', [name, '--project', newproject])
     unless roles.empty?
       return # if already set, just skip
     end
@@ -228,26 +194,11 @@ Puppet::Type.type(:keystone_user).provide(
     # ok for a user to have the _member_ role and another role.
     default_role = "_member_"
     begin
-      request('role', 'show', default_role, resource[:auth])
+      request('role', 'show', [default_role])
     rescue
       debug("Keystone role #{default_role} does not exist - creating")
-      request('role', 'create', default_role, resource[:auth])
-    end
-    request('role', 'add', default_role, resource[:auth],
-            '--project', newproject, '--user', resource[:name])
-  end
-
-  def flush
-    options = []
-    if @property_flush
-      (options << '--enable') if @property_flush[:enabled] == :true
-      (options << '--disable') if @property_flush[:enabled] == :false
-      # There is a --description flag for the set command, but it does not work if the value is empty
-      (options << '--password' << resource[:password]) if @property_flush[:password]
-      (options << '--email'    << resource[:email])    if @property_flush[:email]
-      # project handled in tenant= separately
-      request('user', 'set', resource[:name], resource[:auth], options) unless options.empty?
+      request('role', 'create', [default_role])
     end
+    request('role', 'add', [default_role, '--project', newproject, '--user', name])
   end
-
 end
index 5b9a1b58728b16c422769dfd0d34b030424bbf49..da2b87044bf420727ec157ba3b2114c162e3da1e 100644 (file)
@@ -7,26 +7,41 @@ Puppet::Type.type(:keystone_user_role).provide(
 
   desc "Provider to manage keystone role assignments to users."
 
+  @credentials = Puppet::Provider::Openstack::CredentialsV2_0.new
+
+  def initialize(value={})
+    super(value)
+    @property_flush = {}
+  end
+
   def create
     properties = []
     properties << '--project' << get_project
     properties << '--user' << get_user
     if resource[:roles]
       resource[:roles].each do |role|
-        request('role', 'add', role, resource[:auth], properties)
+        self.class.request('role', 'add', [role] + properties)
+      end
+    end
+  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)
       end
     end
+    @property_hash[:ensure] = :absent
   end
 
   def exists?
-    # If we just ran self.instances, no need to make the request again
-    # instance() will find it cached in @user_role_hash
-    if self.class.user_role_hash
-      return ! instance(resource[:name]).empty?
-    # If we don't have the hash ready, we don't need to rebuild the
-    # whole thing just to check on one particular user/role
+    if @user_role_hash
+      return ! @property_hash[:name].empty?
     else
-      roles = request('user role', 'list', nil, resource[:auth], ['--project', get_project, get_user])
+      roles = self.class.request('user role', 'list', [get_user, '--project', get_project])
       # 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
@@ -44,19 +59,6 @@ Puppet::Type.type(:keystone_user_role).provide(
     end
   end
 
-  def destroy
-    properties = []
-    properties << '--project' << get_project
-    properties << '--user' << get_user
-    if @property_hash[:roles]
-      @property_hash[:roles].each do |role|
-        request('role', 'remove', role, resource[:auth], properties)
-      end
-    end
-    @property_hash[:ensure] = :absent
-  end
-
-
   def roles
     @property_hash[:roles]
   end
@@ -69,14 +71,13 @@ Puppet::Type.type(:keystone_user_role).provide(
     user = get_user
     project = get_project
     add.each do |role_name|
-      request('role', 'add', role_name, resource[:auth], ['--project', project, '--user', user])
+      self.class.request('role', 'add', [role_name, '--project', project, '--user', user])
     end
     remove.each do |role_name|
-      request('role', 'remove', role_name, resource[:auth], ['--project', project, '--user', user])
+      self.class.request('role', 'remove', [role_name, '--project', project, '--user', user])
     end
   end
 
-
   def self.instances
     instances = build_user_role_hash
     instances.collect do |title, roles|
@@ -88,10 +89,6 @@ Puppet::Type.type(:keystone_user_role).provide(
     end
   end
 
-  def instance(name)
-    self.class.user_role_hash.select { |role_name, roles| role_name == name } || {}
-  end
-
   private
 
   def get_user
@@ -102,50 +99,26 @@ Puppet::Type.type(:keystone_user_role).provide(
     resource[:name].rpartition('@').last
   end
 
-  # We split get_projects into class and instance methods
-  # so that the appropriate request method gets called
-  def get_projects
-    request('project', 'list', nil, resource[:auth]).collect do |project|
-      project[:name]
-    end
-  end
-
   def self.get_projects
-    request('project', 'list', nil, nil).collect do |project|
-      project[:name]
-    end
-  end
-
-  def get_users(project)
-    request('user', 'list', nil, resource[:auth], ['--project', project]).collect do |user|
-      user[:name]
-    end
+    request('project', 'list').collect { |project| project[:name] }
   end
 
   def self.get_users(project)
-    request('user', 'list', nil, nil, ['--project', project]).collect do |user|
-      user[:name]
-    end
+    request('user', 'list', ['--project', project]).collect { |user| user[:name] }
   end
 
-  # Class methods for caching user_role_hash so both class and instance
-  # methods can access the value
   def self.set_user_role_hash(user_role_hash)
     @user_role_hash = user_role_hash
   end
 
-  def self.user_role_hash
-    @user_role_hash
-  end
-
   def self.build_user_role_hash
-    hash = user_role_hash || {}
+    hash = @user_role_hash || {}
     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', nil, nil, ['--project', project, user])
+        user_roles = request('user role', 'list', [user, '--project', project])
         hash["#{user}@#{project}"] = []
         user_roles.each do |role|
           hash["#{user}@#{project}"] << role[:name]
@@ -155,5 +128,4 @@ Puppet::Type.type(:keystone_user_role).provide(
     set_user_role_hash(hash)
     hash
   end
-
 end
diff --git a/3rdparty/modules/keystone/lib/puppet/provider/openstack.rb b/3rdparty/modules/keystone/lib/puppet/provider/openstack.rb
deleted file mode 100644 (file)
index 8236df7..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-# TODO: This needs to be extracted out into openstacklib in the Kilo cycle
-require 'csv'
-require 'puppet'
-
-class Puppet::Error::OpenstackAuthInputError < Puppet::Error
-end
-
-class Puppet::Error::OpenstackUnauthorizedError < Puppet::Error
-end
-
-class Puppet::Provider::Openstack < Puppet::Provider
-
-  initvars # so commands will work
-  commands :openstack => 'openstack'
-
-  def request(service, action, object, credentials, *properties)
-    if password_credentials_set?(credentials)
-      auth_args = password_auth_args(credentials)
-    elsif openrc_set?(credentials)
-      credentials = get_credentials_from_openrc(credentials['openrc'])
-      auth_args = password_auth_args(credentials)
-    elsif service_credentials_set?(credentials)
-      auth_args = token_auth_args(credentials)
-    elsif env_vars_set?
-      # noop; auth needs no extra arguments
-      auth_args = nil
-    else  # All authentication efforts failed
-      raise(Puppet::Error::OpenstackAuthInputError, 'No credentials provided.')
-    end
-    args = [object, properties, auth_args].flatten.compact
-    authenticate_request(service, action, args)
-  end
-
-  def self.request(service, action, object, *properties)
-    if env_vars_set?
-      # noop; auth needs no extra arguments
-      auth_args = nil
-    else  # All authentication efforts failed
-      raise(Puppet::Error::OpenstackAuthInputError, 'No credentials provided.')
-    end
-    args = [object, properties, auth_args].flatten.compact
-    authenticate_request(service, action, args)
-  end
-
-  # Returns an array of hashes, where the keys are the downcased CSV headers
-  # with underscores instead of spaces
-  def self.authenticate_request(service, action, *args)
-    rv = nil
-    timeout = 10
-    end_time = Time.now.to_i + timeout
-    loop do
-      begin
-        if(action == 'list')
-          response = openstack(service, action, '--quiet', '--format', 'csv', args)
-          response = parse_csv(response)
-          keys = response.delete_at(0) # ID,Name,Description,Enabled
-          rv = response.collect do |line|
-            hash = {}
-            keys.each_index do |index|
-              key = keys[index].downcase.gsub(/ /, '_').to_sym
-              hash[key] = line[index]
-            end
-            hash
-          end
-        elsif(action == 'show' || action == 'create')
-          rv = {}
-          # shell output is name="value"\nid="value2"\ndescription="value3" etc.
-          openstack(service, action, '--format', 'shell', args).split("\n").each do |line|
-            # key is everything before the first "="
-            key, val = line.split("=", 2)
-            next unless val # Ignore warnings
-            # value is everything after the first "=", with leading and trailing double quotes stripped
-            val = val.gsub(/\A"|"\Z/, '')
-            rv[key.downcase.to_sym] = val
-          end
-        else
-          rv = openstack(service, action, args)
-        end
-        break
-      rescue Puppet::ExecutionFailure => e
-        if e.message =~ /HTTP 401/
-          raise(Puppet::Error::OpenstackUnauthorizedError, 'Could not authenticate.')
-        elsif e.message =~ /Unable to establish connection/
-          current_time = Time.now.to_i
-          if current_time > end_time
-            break
-          else
-            wait = end_time - current_time
-            Puppet::debug("Non-fatal error: \"#{e.message}\"; retrying for #{wait} more seconds.")
-            if wait > timeout - 2 # Only notice the first time
-              notice("#{service} service is unavailable. Will retry for up to #{wait} seconds.")
-            end
-          end
-          sleep(2)
-        else
-          raise e
-        end
-      end
-    end
-    return rv
-  end
-
-  def authenticate_request(service, action, *args)
-    self.class.authenticate_request(service, action, *args)
-  end
-
-  private
-
-  def password_credentials_set?(auth_params)
-    auth_params && auth_params['username'] && auth_params['password'] && auth_params['tenant_name'] && auth_params['auth_url']
-  end
-
-
-  def openrc_set?(auth_params)
-    auth_params && auth_params['openrc']
-  end
-
-
-  def service_credentials_set?(auth_params)
-    auth_params && auth_params['token'] && auth_params['auth_url']
-  end
-
-
-  def self.env_vars_set?
-    ENV['OS_USERNAME'] && ENV['OS_PASSWORD'] && ENV['OS_TENANT_NAME'] && ENV['OS_AUTH_URL']
-  end
-
-
-  def env_vars_set?
-    self.class.env_vars_set?
-  end
-
-
-
-  def self.password_auth_args(credentials)
-    ['--os-username',    credentials['username'],
-     '--os-password',    credentials['password'],
-     '--os-tenant-name', credentials['tenant_name'],
-     '--os-auth-url',    credentials['auth_url']]
-  end
-
-  def password_auth_args(credentials)
-    self.class.password_auth_args(credentials)
-  end
-
-
-  def self.token_auth_args(credentials)
-    ['--os-token',    credentials['token'],
-     '--os-url', credentials['auth_url']]
-  end
-
-  def token_auth_args(credentials)
-    self.class.token_auth_args(credentials)
-  end
-
-  def get_credentials_from_openrc(file)
-    creds = {}
-    File.open(file).readlines.delete_if{|l| l=~ /^#/}.each do |line|
-      key, value = line.split('=')
-      key = key.split(' ').last.downcase.sub(/^os_/, '')
-      value = value.chomp.gsub(/'/, '')
-      creds[key] = value
-    end
-    return creds
-  end
-
-
-  def self.get_credentials_from_env
-    env = ENV.to_hash.dup.delete_if { |key, _| ! (key =~ /^OS_/) }
-    credentials = {}
-    env.each do |name, value|
-      credentials[name.downcase.sub(/^os_/, '')] = value
-    end
-    credentials
-  end
-
-  def get_credentials_from_env
-    self.class.get_credentials_from_env
-  end
-
-  def self.parse_csv(text)
-    # Ignore warnings - assume legitimate output starts with a double quoted
-    # string.  Errors will be caught and raised prior to this
-    text = text.split("\n").drop_while { |line| line !~ /^\".*\"/ }.join("\n")
-    return CSV.parse(text + "\n")
-  end
-
-end
index 4b0e6df9caaa679f66102f409b0692bd36c9fc26..43c5eb2ea80379ec05296a331d6ebbffa698f844 100644 (file)
@@ -1,6 +1,7 @@
 # LP#1408531
 File.expand_path('../..', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
-require 'puppet/util/openstack'
+File.expand_path('../../../../openstacklib/lib', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
+
 Puppet::Type.newtype(:keystone_endpoint) do
 
   desc 'Type for managing keystone endpoints.'
@@ -38,10 +39,4 @@ Puppet::Type.newtype(:keystone_endpoint) do
     (region, service_name) = self[:name].split('/')
     [service_name]
   end
-
-  auth_param_doc=<<EOT
-If no other credentials are present, the provider will search in
-/etc/keystone/keystone.conf for an admin token and auth url.
-EOT
-  Puppet::Util::Openstack.add_openstack_type_methods(self, auth_param_doc)
 end
index c6e7d1d45fbcb3444450a8d482f3cf87d2830799..3636afb279da9500f279f24ec540ce9b4cf8a35c 100644 (file)
@@ -1,6 +1,7 @@
 # LP#1408531
 File.expand_path('../..', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
-require 'puppet/util/openstack'
+File.expand_path('../../../../openstacklib/lib', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
+
 Puppet::Type.newtype(:keystone_role) do
 
   desc <<-EOT
@@ -24,10 +25,4 @@ Puppet::Type.newtype(:keystone_role) do
   autorequire(:service) do
     ['keystone']
   end
-
-  auth_param_doc=<<EOT
-If no other credentials are present, the provider will search in
-/etc/keystone/keystone.conf for an admin token and auth url.
-EOT
-  Puppet::Util::Openstack.add_openstack_type_methods(self, auth_param_doc)
 end
index 9b2c1d9d40c457755720bc303ffb9408410802cc..a4be4edae8f45bb71034a794be50f1f1bcd4074b 100644 (file)
@@ -1,6 +1,7 @@
 # LP#1408531
 File.expand_path('../..', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
-require 'puppet/util/openstack'
+File.expand_path('../../../../openstacklib/lib', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
+
 Puppet::Type.newtype(:keystone_service) do
 
   desc 'This type can be used to manage keystone services.'
@@ -37,10 +38,4 @@ Puppet::Type.newtype(:keystone_service) do
   autorequire(:service) do
     ['keystone']
   end
-
-  auth_param_doc=<<EOT
-If no other credentials are present, the provider will search in
-/etc/keystone/keystone.conf for an admin token and auth url.
-EOT
-  Puppet::Util::Openstack.add_openstack_type_methods(self, auth_param_doc)
 end
index 3e1de7f3784e649f6dd1d06afbd9dcc31f456885..6195d23f90b3380c7dc39281375a7215c3682f8d 100644 (file)
@@ -1,6 +1,7 @@
 # LP#1408531
 File.expand_path('../..', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
-require 'puppet/util/openstack'
+File.expand_path('../../../../openstacklib/lib', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
+
 Puppet::Type.newtype(:keystone_tenant) do
 
   desc 'This type can be used to manage keystone tenants.'
@@ -40,10 +41,4 @@ Puppet::Type.newtype(:keystone_tenant) do
   autorequire(:service) do
     ['keystone']
   end
-
-  auth_param_doc=<<EOT
-If no other credentials are present, the provider will search in
-/etc/keystone/keystone.conf for an admin token and auth url.
-EOT
-  Puppet::Util::Openstack.add_openstack_type_methods(self, auth_param_doc)
 end
index 2186169482e8ec2b2fbb500efe415ab03597d4cb..b484e7c5fd2a2cb2b71bf680e4bf5086804a5adb 100644 (file)
@@ -1,6 +1,7 @@
 # LP#1408531
 File.expand_path('../..', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
-require 'puppet/util/openstack'
+File.expand_path('../../../../openstacklib/lib', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
+
 Puppet::Type.newtype(:keystone_user) do
 
   desc 'Type for managing keystone users.'
@@ -76,10 +77,4 @@ Puppet::Type.newtype(:keystone_user) do
   autorequire(:service) do
     ['keystone']
   end
-
-  auth_param_doc=<<EOT
-If no other credentials are present, the provider will search in
-/etc/keystone/keystone.conf for an admin token and auth url.
-EOT
-  Puppet::Util::Openstack.add_openstack_type_methods(self, auth_param_doc)
 end
index 9ac24e34e4515561e86f789dadebe354470186ba..502dc39761cb4122e58ee54ad04986a518f9540f 100644 (file)
@@ -1,6 +1,7 @@
 # LP#1408531
 File.expand_path('../..', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
-require 'puppet/util/openstack'
+File.expand_path('../../../../openstacklib/lib', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) }
+
 Puppet::Type.newtype(:keystone_user_role) do
 
   desc <<-EOT
@@ -15,7 +16,6 @@ Puppet::Type.newtype(:keystone_user_role) do
   ensurable
 
   newparam(:name, :namevar => true) do
-    newvalues(/^\S+@\S+$/)
   end
 
   newproperty(:roles,  :array_matching => :all) do
@@ -42,10 +42,4 @@ Puppet::Type.newtype(:keystone_user_role) do
   autorequire(:service) do
     ['keystone']
   end
-
-  auth_param_doc=<<EOT
-If no other credentials are present, the provider will search in
-/etc/keystone/keystone.conf for an admin token and auth url.
-EOT
-  Puppet::Util::Openstack.add_openstack_type_methods(self, auth_param_doc)
 end
diff --git a/3rdparty/modules/keystone/lib/puppet/util/openstack.rb b/3rdparty/modules/keystone/lib/puppet/util/openstack.rb
deleted file mode 100644 (file)
index 947aa35..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-# TODO: This should be extracted into openstacklib during the kilo cycle
-# Add the auth parameter to whatever type is given
-module Puppet::Util::Openstack
-  def self.add_openstack_type_methods(type, comment)
-
-    type.newparam(:auth) do
-
-      desc <<EOT
-Hash of authentication credentials. Credentials can be specified as
-password credentials, e.g.:
-
-auth => {
-  'username'    => 'test',
-  'password'    => 'passw0rd',
-  'tenant_name' => 'test',
-  'auth_url'    => 'http://localhost:35357/v2.0',
-}
-
-or a path to an openrc file containing these credentials, e.g.:
-
-auth => {
-  'openrc' => '/root/openrc',
-}
-
-or a service token and host, e.g.:
-
-auth => {
-  'service_token' => 'ADMIN',
-  'auth_url'    => 'http://localhost:35357/v2.0',
-}
-
-If not present, the provider will look for environment variables for
-password credentials.
-
-#{comment}
-EOT
-
-      validate do |value|
-        raise(Puppet::Error, 'This property must be a hash') unless value.is_a?(Hash)
-      end
-    end
-
-    type.autorequire(:package) do
-      'python-openstackclient'
-    end
-
-  end
-end
index d400f39702bad0db4998d6abb07ad718e3a620bb..84a6e08ce7af664b435c97469fe8bf2da6ad4a5a 100644 (file)
@@ -5,7 +5,8 @@
 # === Parameters
 #
 # [*ensure*]
-#   (optional) Ensure state of the package. Defaults to 'present'.
+#   (optional) Ensure state of the package.
+#   Defaults to 'present'.
 #
 class keystone::client (
   $ensure = 'present'
index 3e046f4a29702e9fd9fc4c650fea25756c01fec6..dc94896cdc8be613f954921c3180cd199cb90a2d 100644 (file)
@@ -5,19 +5,39 @@
 #
 # == parameters
 #
-# [password] Password that will be used for the keystone db user.
-#   Optional. Defaults to: 'keystone_default_password'
+# [*password*]
+#   (Mandatory) Password to connect to the database.
+#   Defaults to 'false'.
 #
-# [dbname] Name of keystone database. Optional. Defaults to keystone.
+# [*dbname*]
+#   (Optional) Name of the database.
+#   Defaults to 'keystone'.
 #
-# [user] Name of keystone user. Optional. Defaults to keystone.
+# [*user*]
+#   (Optional) User to connect to the database.
+#   Defaults to 'keystone'.
 #
-# [host] Host where user should be allowed all priveleges for database.
-# Optional. Defaults to 127.0.0.1.
+# [*host*]
+#   (Optional) The default source host user is allowed to connect from.
+#   Defaults to '127.0.0.1'
 #
-# [allowed_hosts] Hosts allowed to use the database
+# [*allowed_hosts*]
+#   (Optional) Other hosts the user is allowed to connect from.
+#   Defaults to 'undef'.
 #
-# [*mysql_module*] Deprecated. Does nothing.
+# [*charset*]
+#   (Optional) The database charset.
+#   Defaults to 'utf8'
+#
+# [*collate*]
+#   (Optional) The database collate.
+#   Only used with mysql modules >= 2.2.
+#   Defaults to 'utf8_general_ci'
+#
+# === Deprecated Parameters
+#
+# [*mysql_module*]
+#   (Optional) Does nothing.
 #
 # == Dependencies
 #   Class['mysql::server']
@@ -37,7 +57,7 @@ class keystone::db::mysql(
   $user          = 'keystone',
   $host          = '127.0.0.1',
   $charset       = 'utf8',
-  $collate       = 'utf8_unicode_ci',
+  $collate       = 'utf8_general_ci',
   $mysql_module  = undef,
   $allowed_hosts = undef
 ) {
index 3d7eb73d785288cebaa7799de88b369d47029f3e..4bf5a6a75524970ae17392b9a3b09f64c4f38fad 100644 (file)
@@ -1,47 +1,57 @@
+# == Class: keystone::db::postgresql
 #
-# implements postgresql backend for keystone
+# Class that configures postgresql for keystone
+# Requires the Puppetlabs postgresql module.
 #
-# This class can be used to create tables, users and grant
-# privelege for a postgresql keystone database.
-#
-# Requires Puppetlabs Postgresql module.
+# == Authors
 #
-# [*Parameters*]
+#   Stackforge Contributors puppet-openstack@puppetlabs.com
+#   Etienne Pelletier epelletier@morphlabs.com
 #
-# [password] Password that will be used for the keystone db user.
-#   Optional. Defaults to: 'keystone_default_password'
+# == Copyright
 #
-# [dbname] Name of keystone database. Optional. Defaults to keystone.
+# Copyright 2013-2014 Stackforge Contributors
+# Copyright 2012 Etienne Pelletier, unless otherwise noted.
 #
-# [user] Name of keystone user. Optional. Defaults to keystone.
+# === Parameters
 #
-# == Dependencies
-#   Class['postgresql::server']
+# [*password*]
+#   (Required) Password to connect to the database.
 #
-# == Examples
-# == Authors
+# [*dbname*]
+#   (Optional) Name of the database.
+#   Defaults to 'keystone'.
 #
-#   Etienne Pelletier epelletier@morphlabs.com
+# [*user*]
+#   (Optional) User to connect to the database.
+#   Defaults to 'keystone'.
 #
-# == Copyright
+#  [*encoding*]
+#    (Optional) The charset to use for the database.
+#    Default to undef.
 #
-# Copyright 2012 Etienne Pelletier, unless otherwise noted.
+#  [*privileges*]
+#    (Optional) Privileges given to the database user.
+#    Default to 'ALL'
 #
 class keystone::db::postgresql(
   $password,
-  $dbname        = 'keystone',
-  $user          = 'keystone'
+  $dbname     = 'keystone',
+  $user       = 'keystone',
+  $encoding   = undef,
+  $privileges = 'ALL',
 ) {
 
   Class['keystone::db::postgresql'] -> Service<| title == 'keystone' |>
 
-  require postgresql::python
-
-  postgresql::db { $dbname:
-    user      => $user,
-    password  => $password,
+  ::openstacklib::db::postgresql { 'keystone':
+    password_hash => postgresql_password($user, $password),
+    dbname        => $dbname,
+    user          => $user,
+    encoding      => $encoding,
+    privileges    => $privileges,
   }
 
-  Postgresql::Db[$dbname] ~> Exec<| title == 'keystone-manage db_sync' |>
+  ::Openstacklib::Db::Postgresql['keystone'] ~> Exec<| title == 'keystone-manage db_sync' |>
 
 }
index 3e68113c2cbb784f426799a57919357f42f4a0f4..f52800f23b159302500bdeb6784abe851cb89eb0 100644 (file)
@@ -1,6 +1,12 @@
 #
 # Installs keystone from source. This is not yet fully implemented
 #
+# == Parameters
+#
+# [*source_dir*]
+#   (optional) The source dire for dev installation
+#   Defaults to '/usr/local/keystone'
+#
 # == Dependencies
 # == Examples
 # == Authors
index c713800f1e4510b0db1e9354d3cb8f9d7acbba2d..6c821f4755793bccaeb7685c1aa2975a275a1d4b 100644 (file)
 # [*version*]
 #   (optional) API version for endpoint. Appended to all endpoint urls. (Defaults to 'v2.0')
 #
-# [*public_protocol*]
-#   (optional) DEPRECATED: Use public_url instead.
-#   Protocol for public access to keystone endpoint. (Defaults to 'http')
-#   Setting this parameter overrides public_url parameter.
-#
-# [*public_address*]
-#   (optional) DEPRECATED: Use public_url instead.
-#   Public address for keystone endpoint. (Defaults to '127.0.0.1')
-#   Setting this parameter overrides public_url parameter.
-#
-# [*public_port*]
-#   (optional) DEPRECATED: Use public_url instead.
-#   Port for non-admin access to keystone endpoint. (Defaults to 5000)
-#   Setting this parameter overrides public_url parameter.
-#
-# [*internal_address*]
-#   (optional) DEPRECATED: Use internal_url instead.
-#   Internal address for keystone endpoint. (Defaults to '127.0.0.1')
-#   Setting this parameter overrides internal_url parameter.
-#
-# [*internal_port*]
-#   (optional) DEPRECATED: Use internal_url instead.
-#   Port for internal access to keystone endpoint. (Defaults to $public_port)
-#   Setting this parameter overrides internal_url parameter.
-#
-# [*admin_address*]
-#   (optional) DEPRECATED: Use admin_url instead.
-#   Admin address for keystone endpoint. (Defaults to '127.0.0.1')
-#   Setting this parameter overrides admin_url parameter.
-#
-# [*admin_port*]
-#   (optional) DEPRECATED: Use admin_url instead.
-#   Port for admin access to keystone endpoint. (Defaults to 35357)
-#   Setting this parameter overrides admin_url parameter.
-#
-# === Deprecation notes
-#
-# If any value is provided for public_protocol, public_address or public_port parameters,
-# public_url will be completely ignored. The same applies for internal and admin parameters.
-#
 # === Examples
 #
 #  class { 'keystone::endpoint':
@@ -76,76 +36,17 @@ class keystone::endpoint (
   $admin_url         = 'http://127.0.0.1:35357',
   $version           = 'v2.0',
   $region            = 'RegionOne',
-  # DEPRECATED PARAMETERS
-  $public_protocol   = undef,
-  $public_address    = undef,
-  $public_port       = undef,
-  $internal_address  = undef,
-  $internal_port     = undef,
-  $admin_address     = undef,
-  $admin_port        = undef,
 ) {
 
-  warning('keystone::endpoint class is deprecated, use keystone::resource::service_identity instead.')
-
-  if $public_port {
-    warning('The public_port parameter is deprecated, use public_url instead.')
-  }
-
-  if $public_protocol {
-    warning('The public_protocol parameter is deprecated, use public_url instead.')
-  }
-
-  if $public_address {
-    warning('The public_address parameter is deprecated, use public_url instead.')
-  }
-
-  if $internal_address {
-    warning('The internal_address parameter is deprecated, use internal_url instead.')
-  }
-
-  if $internal_port {
-    warning('The internal_port parameter is deprecated, use internal_url instead.')
-  }
-
-  if $admin_address {
-    warning('The admin_address parameter is deprecated, use admin_url instead.')
-  }
+  $public_url_real = "${public_url}/${version}"
+  $admin_url_real = "${admin_url}/${version}"
 
-  if $admin_port {
-    warning('The admin_port parameter is deprecated, use admin_url instead.')
+  if $internal_url {
+    $internal_url_real = "${internal_url}/${version}"
+  } else {
+    $internal_url_real = "${public_url}/${version}"
   }
 
-  $public_url_real = inline_template('<%=
-    if (!@public_protocol.nil?) || (!@public_address.nil?) || (!@public_port.nil?)
-      @public_protocol ||= "http"
-      @public_address ||= "127.0.0.1"
-      @public_port ||= "5000"
-      "#{@public_protocol}://#{@public_address}:#{@public_port}/#{@version}"
-    else
-      "#{@public_url}/#{@version}"
-    end %>')
-
-  $internal_url_real = inline_template('<%=
-    if (!@internal_address.nil?) || (!@internal_port.nil?) || (!@public_port.nil?)
-      @internal_address ||= @public_address ||= "127.0.0.1"
-      @internal_port ||= @public_port ||= "5000"
-      "http://#{@internal_address}:#{@internal_port}/#{@version}"
-    elsif (!@internal_url.nil?)
-      "#{@internal_url}/#{@version}"
-    else
-      "#{@public_url}/#{@version}"
-    end %>')
-
-  $admin_url_real = inline_template('<%=
-    if (!@admin_address.nil?) || (!@admin_port.nil?)
-      @admin_address ||= "127.0.0.1"
-      @admin_port ||= "35357"
-      "http://#{@admin_address}:#{@admin_port}/#{@version}"
-    else
-      "#{@admin_url}/#{@version}"
-    end %>')
-
   keystone::resource::service_identity { 'keystone':
     configure_user      => false,
     configure_user_role => false,
index d43bcd2ee57f52d8db7857eb747a25e315873001..20c2011e318bcd25156700e38c4f17c33f94f73a 100644 (file)
 #
 # == Parameters
 #
-#   [package_ensure] Desired ensure state of packages. Optional. Defaults to present.
-#     accepts latest or specific versions.
-#   [bind_host] Host that keystone binds to.
-#   [bind_port] Port that keystone binds to.
-#   [public_port]
-#   [compute_port]
-#   [admin_port]
-#   [admin_port] Port that can be used for admin tasks.
-#   [admin_token] Admin token that can be used to authenticate as a keystone
-#     admin. Required.
-#   [verbose] Rather keystone should log at verbose level. Optional.
-#     Defaults to False.
-#   [debug] Rather keystone should log at debug level. Optional.
-#     Defaults to False.
-#   [use_syslog] Use syslog for logging. Optional.
-#     Defaults to False.
-#   [log_facility] Syslog facility to receive log lines. Optional.
-#   [catalog_type] Type of catalog that keystone uses to store endpoints,services. Optional.
-#     Defaults to sql. (Also accepts template)
-#   [catalog_driver] Catalog driver used by Keystone to store endpoints and services. Optional.
-#     Setting this value will override and ignore catalog_type.
-#   [catalog_template_file] Path to the catalog used if catalog_type equals 'template'.
-#     Defaults to '/etc/keystone/default_catalog.templates'
-#   [token_provider] Format keystone uses for tokens. Optional.
-#     Defaults to 'keystone.token.providers.uuid.Provider'
-#     Supports PKI and UUID.
-#   [token_driver] Driver to use for managing tokens.
-#     Optional.  Defaults to 'keystone.token.persistence.backends.sql.Token'
-#   [token_expiration] Amount of time a token should remain valid (seconds).
-#     Optional.  Defaults to 3600 (1 hour).
-#   [token_format] Deprecated: Use token_provider instead.
-#   [cache_dir] Directory created when token_provider is pki. Optional.
-#     Defaults to /var/cache/keystone.
-#
-#   [memcache_servers]
-#     List of memcache servers in format of server:port.
-#     Used with token_driver 'keystone.token.backends.memcache.Token'.
-#     Optional. Defaults to false. Example: ['localhost:11211']
-#
-#   [cache_backend]
-#     Dogpile.cache backend module. It is recommended that Memcache with pooling
-#     (keystone.cache.memcache_pool) or Redis (dogpile.cache.redis) be used in production.
-#     This has no effects unless 'memcache_servers' is set.
-#     Optional. Defaults to 'keystone.common.cache.noop'
-#
-#   [cache_backend_argument]
-#     List of arguments in format of argname:value supplied to the backend module.
-#     Specify this option once per argument to be passed to the dogpile.cache backend.
-#     This has no effects unless 'memcache_servers' is set.
-#     Optional. Default to undef.
-#
-#   [debug_cache_backend]
-#     Extra debugging from the cache backend (cache keys, get/set/delete calls).
-#     This has no effects unless 'memcache_servers' is set.
-#     Optional. Default to false.
-#
-#   [token_caching]
-#     Toggle for token system caching. This has no effects unless 'memcache_servers' is set.
-#     Optional. Default to true.
-#
-#   [enabled] If the keystone services should be enabled. Optional. Default to true.
-#
-#   [*database_connection*]
-#     (optional) Url used to connect to database.
-#     Defaults to sqlite:////var/lib/keystone/keystone.db
-#
-#   [*sql_connection*]
-#     (optional) Deprecated. Use database_connection instead.
-#
-#   [*database_idle_timeout*]
-#     (optional) Timeout when db connections should be reaped.
-#     Defaults to 200.
-#
-#   [*idle_timeout*]
-#     (optional) Deprecated. Use database_idle_timeout instead.
-#
-#   [enable_pki_setup] Enable call to pki_setup to generate the cert for signing pki tokens and
-#     revocation lists if it doesn't already exist. This generates a cert and key stored in file
-#     locations based on the signing_certfile and signing_keyfile paramters below. If you are
-#     providing your own signing cert, make this false.
-#   [signing_certfile] Location of the cert file for signing pki tokens and revocation lists.
-#     Optional. Note that if this file already exists (i.e. you are providing your own signing cert),
-#     the file will not be overwritten, even if enable_pki_setup is set to true.
-#     Default: /etc/keystone/ssl/certs/signing_cert.pem
-#   [signing_keyfile] Location of the key file for signing pki tokens and revocation lists. Optional.
-#     Note that if this file already exists (i.e. you are providing your own signing cert), the file
-#     will not be overwritten, even if enable_pki_setup is set to true.
-#     Default: /etc/keystone/ssl/private/signing_key.pem
-#   [signing_ca_certs] Use this CA certs file along with signing_certfile/signing_keyfile for
-#     signing pki tokens and revocation lists. Optional. Default: /etc/keystone/ssl/certs/ca.pem
-#   [signing_ca_key] Use this CA key file along with signing_certfile/signing_keyfile for signing
-#     pki tokens and revocation lists. Optional. Default: /etc/keystone/ssl/private/cakey.pem
-#
-#   [*signing_cert_subject*]
+# [*package_ensure*]
+#   (optional) Desired ensure state of packages.
+#   accepts latest or specific versions.
+#   Defaults to present.
+#
+# [*client_package_ensure*]
+#   (optional) Desired ensure state of the client package.
+#   accepts latest or specific versions.
+#   Defaults to present.
+#
+# [*public_port*]
+#   (optional) Port that keystone binds to.
+#   Defaults to '5000'
+#
+# [*compute_port*]
+#   (optional) DEPRECATED The port for compute servie.
+#   Defaults to '8774'
+#
+# [*admin_port*]
+#   (optional) Port that can be used for admin tasks.
+#   Defaults to '35357'
+#
+# [*admin_token*]
+#   Admin token that can be used to authenticate as a keystone
+#   admin. Required.
+#
+# [*verbose*]
+#   (optional) Rather keystone should log at verbose level.
+#   Defaults to false.
+#
+# [*debug*]
+#   (optional) Rather keystone should log at debug level.
+#   Defaults to False.
+#
+# [*use_syslog*]
+#   (optional) Use syslog for logging.
+#   Defaults to false.
+#
+# [*log_facility*]
+#   (optional) Syslog facility to receive log lines.
+#   Defaults to 'LOG_USER'.
+#
+# [*catalog_type*]
+#   (optional) Type of catalog that keystone uses to store endpoints,services.
+#   Defaults to sql. (Also accepts template)
+#
+# [*catalog_driver*]
+#   (optional) Catalog driver used by Keystone to store endpoints and services.
+#   Setting this value will override and ignore catalog_type.
+#   Defaults to false.
+#
+# [*catalog_template_file*]
+#   (optional) Path to the catalog used if catalog_type equals 'template'.
+#   Defaults to '/etc/keystone/default_catalog.templates'
+#
+# [*token_provider*]
+#   (optional) Format keystone uses for tokens.
+#   Defaults to 'keystone.token.providers.uuid.Provider'
+#   Supports PKI, PKIZ, Fernet, and UUID.
+#
+# [*token_driver*]
+#   (optional) Driver to use for managing tokens.
+#   Defaults to 'keystone.token.persistence.backends.sql.Token'
+#
+# [*token_expiration*]
+#   (optional) Amount of time a token should remain valid (seconds).
+#   Defaults to 3600 (1 hour).
+#
+# [*revoke_driver*]
+#   (optional) Driver for token revocation.
+#   Defaults to 'keystone.contrib.revoke.backends.sql.Revoke'
+#
+# [*cache_dir*]
+#   (optional) Directory created when token_provider is pki.
+#   Defaults to /var/cache/keystone.
+#
+# [*memcache_servers*]
+#   (optional) List of memcache servers in format of server:port.
+#   Used with token_driver 'keystone.token.backends.memcache.Token'.
+#   Defaults to false. Example: ['localhost:11211']
+#
+# [*cache_backend*]
+#   (optional) Dogpile.cache backend module. It is recommended that Memcache with pooling
+#   (keystone.cache.memcache_pool) or Redis (dogpile.cache.redis) be used in production.
+#   This has no effects unless 'memcache_servers' is set.
+#   Defaults to 'keystone.common.cache.noop'
+#
+# [*cache_backend_argument*]
+#   (optional) List of arguments in format of argname:value supplied to the backend module.
+#   Specify this option once per argument to be passed to the dogpile.cache backend.
+#   This has no effects unless 'memcache_servers' is set.
+#   Default to undef.
+#
+# [*debug_cache_backend*]
+#   (optional) Extra debugging from the cache backend (cache keys, get/set/delete calls).
+#   This has no effects unless 'memcache_servers' is set.
+#   Default to false.
+#
+# [*token_caching*]
+#   (optional) Toggle for token system caching. This has no effects unless 'memcache_servers' is set.
+#   Default to true.
+#
+# [*manage_service*]
+#   (Optional) If Puppet should manage service startup / shutdown.
+#   Defaults to true.
+#
+# [*enabled*]
+#  (optional) If the keystone services should be enabled.
+#   Default to true.
+#
+# [*database_connection*]
+#   (optional) Url used to connect to database.
+#   Defaults to sqlite:////var/lib/keystone/keystone.db
+#
+# [*database_idle_timeout*]
+#   (optional) Timeout when db connections should be reaped.
+#   Defaults to 200.
+#
+# [*enable_pki_setup*]
+#   (optional) Enable call to pki_setup to generate the cert for signing pki tokens and
+#   revocation lists if it doesn't already exist. This generates a cert and key stored in file
+#   locations based on the signing_certfile and signing_keyfile paramters below. If you are
+#   providing your own signing cert, make this false.
+#   Default to true.
+#
+# [*signing_certfile*]
+#   (optional) Location of the cert file for signing pki tokens and revocation lists.
+#   Note that if this file already exists (i.e. you are providing your own signing cert),
+#   the file will not be overwritten, even if enable_pki_setup is set to true.
+#   Default: /etc/keystone/ssl/certs/signing_cert.pem
+#
+# [*signing_keyfile*]
+#   (optional) Location of the key file for signing pki tokens and revocation lists.
+#   Note that if this file already exists (i.e. you are providing your own signing cert), the file
+#   will not be overwritten, even if enable_pki_setup is set to true.
+#   Default: /etc/keystone/ssl/private/signing_key.pem
+#
+# [*signing_ca_certs*]
+#   (optional) Use this CA certs file along with signing_certfile/signing_keyfile for
+#   signing pki tokens and revocation lists.
+#   Default: /etc/keystone/ssl/certs/ca.pem
+#
+# [*signing_ca_key*]
+#   (optional) Use this CA key file along with signing_certfile/signing_keyfile for signing
+#   pki tokens and revocation lists.
+#   Default: /etc/keystone/ssl/private/cakey.pem
+#
+# [*signing_cert_subject*]
 #   (optional) Certificate subject (auto generated certificate) for token signing.
 #   Defaults to '/C=US/ST=Unset/L=Unset/O=Unset/CN=www.example.com'
 #
-#   [*signing_key_size*]
+# [*signing_key_size*]
 #   (optional) Key size (in bits) for token signing cert (auto generated certificate)
 #   Defaults to 2048
 #
-#   [rabbit_host] Location of rabbitmq installation. Optional. Defaults to localhost.
-#   [rabbit_port] Port for rabbitmq instance. Optional. Defaults to 5672.
-#   [rabbit_hosts] Location of rabbitmq installation. Optional. Defaults to undef.
-#   [rabbit_password] Password used to connect to rabbitmq. Optional. Defaults to guest.
-#   [rabbit_userid] User used to connect to rabbitmq. Optional. Defaults to guest.
-#   [rabbit_virtual_host] The RabbitMQ virtual host. Optional. Defaults to /.
+# [*rabbit_host*]
+#   (optional) Location of rabbitmq installation.
+#    Defaults to localhost.
 #
-#   [*rabbit_use_ssl*]
-#     (optional) Connect over SSL for RabbitMQ
-#     Defaults to false
+# [*rabbit_port*]
+#   (optional) Port for rabbitmq instance.
+#   Defaults to 5672.
 #
-#   [*kombu_ssl_ca_certs*]
-#     (optional) SSL certification authority file (valid only if SSL enabled).
-#     Defaults to undef
+# [*rabbit_hosts*]
+#   (optional) Location of rabbitmq installation.
+#   Defaults to undef.
 #
-#   [*kombu_ssl_certfile*]
-#     (optional) SSL cert file (valid only if SSL enabled).
-#     Defaults to undef
+# [*rabbit_password*]
+#   (optional) Password used to connect to rabbitmq.
+#   Defaults to guest.
 #
-#   [*kombu_ssl_keyfile*]
-#     (optional) SSL key file (valid only if SSL enabled).
-#     Defaults to undef
+# [*rabbit_userid*]
+#   (optional) User used to connect to rabbitmq.
+#   Defaults to guest.
 #
-#   [*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'
+# [*rabbit_virtual_host*]
+#   (optional) The RabbitMQ virtual host.
+#   Defaults to /.
 #
-#   [notification_driver] RPC driver. Not enabled by default
-#   [notification_topics] AMQP topics to publish to when using the RPC notification driver.
-#   [control_exchange] AMQP exchange to connect to if using RabbitMQ or Qpid
+# [*rabbit_use_ssl*]
+#   (optional) Connect over SSL for RabbitMQ
+#   Defaults to false
+#
+# [*kombu_ssl_ca_certs*]
+#   (optional) SSL certification authority file (valid only if SSL enabled).
+#   Defaults to undef
+#
+# [*kombu_ssl_certfile*]
+#   (optional) SSL cert file (valid only if SSL enabled).
+#   Defaults to undef
+#
+# [*kombu_ssl_keyfile*]
+#   (optional) SSL key file (valid only if SSL enabled).
+#   Defaults to undef
+#
+# [*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'
+#
+# [*notification_driver*]
+#   RPC driver. Not enabled by default
+#
+# [*notification_topics*]
+#   (optional) AMQP topics to publish to when using the RPC notification driver.
+#   Default to false.
+#
+# [*notification_format*]
+#   Format for the notifications. Valid values are 'basic' and 'cadf'.
+#   Default to undef
+#
+# [*control_exchange*]
+#   (optional) AMQP exchange to connect to if using RabbitMQ or Qpid
+#   Default to false.
 #
-#   [*public_bind_host*]
+# [*public_bind_host*]
 #   (optional) The IP address of the public network interface to listen on
-#   Deprecates bind_host
 #   Default to '0.0.0.0'.
 #
-#   [*admin_bind_host*]
+# [*admin_bind_host*]
 #   (optional) The IP address of the public network interface to listen on
-#   Deprecates bind_host
 #   Default to '0.0.0.0'.
 #
-#   [*log_dir*]
+# [*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/keystone'
 #
-#   [*log_file*]
+# [*log_file*]
 #   (optional) Where to log
 #   Defaults to false
 #
-#   [*public_endpoint*]
+# [*public_endpoint*]
 #   (optional) The base public endpoint URL for keystone that are
 #   advertised to clients (NOTE: this does NOT affect how
 #   keystone listens for connections) (string value)
 #   Sample value: 'http://localhost:5000/'
 #   Defaults to false
 #
-#   [*admin_endpoint*]
+# [*admin_endpoint*]
 #   (optional) The base admin endpoint URL for keystone that are
 #   advertised to clients (NOTE: this does NOT affect how keystone listens
 #   for connections) (string value)
 #   Sample value: 'http://localhost:35357/'
 #   Defaults to false
 #
-#   [*enable_ssl*]
+# [*enable_ssl*]
 #   (optional) Toggle for SSL support on the keystone eventlet servers.
 #   (boolean value)
 #   Defaults to false
 #
-#   [*ssl_certfile*]
+# [*ssl_certfile*]
 #   (optional) Path of the certfile for SSL. (string value)
 #   Defaults to '/etc/keystone/ssl/certs/keystone.pem'
 #
-#   [*ssl_keyfile*]
+# [*ssl_keyfile*]
 #   (optional) Path of the keyfile for SSL. (string value)
 #   Defaults to '/etc/keystone/ssl/private/keystonekey.pem'
 #
-#   [*ssl_ca_certs*]
+# [*ssl_ca_certs*]
 #   (optional) Path of the ca cert file for SSL. (string value)
 #   Defaults to '/etc/keystone/ssl/certs/ca.pem'
 #
-#   [*ssl_ca_key*]
+# [*ssl_ca_key*]
 #   (optional) Path of the CA key file for SSL (string value)
 #   Defaults to '/etc/keystone/ssl/private/cakey.pem'
 #
-#   [*ssl_cert_subject*]
+# [*ssl_cert_subject*]
 #   (optional) SSL Certificate Subject (auto generated certificate)
 #   (string value)
 #   Defaults to '/C=US/ST=Unset/L=Unset/O=Unset/CN=localhost'
 #
-#   [*mysql_module*]
+# [*mysql_module*]
 #   (optional) Deprecated. Does nothing.
 #
-#   [*validate_service*]
+# [*validate_service*]
 #   (optional) Whether to validate keystone connections after
 #   the service is started.
 #   Defaults to false
 #
-#   [*validate_insecure*]
+# [*validate_insecure*]
 #   (optional) Whether to validate keystone connections
 #   using the --insecure option with keystone client.
 #   Defaults to false
 #
-#   [*validate_cacert*]
+# [*validate_cacert*]
 #   (optional) Whether to validate keystone connections
 #   using the specified argument with the --os-cacert option
 #   with keystone client.
 #   Defaults to undef
 #
-#   [*validate_auth_url*]
+# [*validate_auth_url*]
 #   (optional) The url to validate keystone against
 #   Defaults to undef
 #
-#   [*service_provider*]
+# [*service_provider*]
 #   (optional) Provider, that can be used for keystone service.
 #   Default value defined in keystone::params for given operation system.
 #   If you use Pacemaker or another Cluster Resource Manager, you can make
 #   custom service provider for changing start/stop/status behavior of service,
 #   and set it here.
 #
-#   [*service_name*]
+# [*service_name*]
 #   (optional) Name of the service that will be providing the
 #   server functionality of keystone.  For example, the default
 #   is just 'keystone', which means keystone will be run as a
 #   web service.  For example, after calling class {'keystone'...}
 #   use class { 'keystone::wsgi::apache'...} to make keystone be
 #   a web app using apache mod_wsgi.
-#   Defaults to 'keystone'
-#   NOTE: validate_service only applies if the value is 'keystone'
+#   Defaults to '$::keystone::params::service_name'
+#   NOTE: validate_service only applies if the default value is used.
+#
+# [*paste_config*]
+#   (optional) Name of the paste configuration file that defines the
+#   available pipelines. (string value)
+#   Defaults to '/usr/share/keystone/keystone-dist-paste.ini' on RedHat and
+#   undef on other platforms.
+#
+# [*max_token_size*]
+#   (optional) maximum allowable Keystone token size
+#   Defaults to undef
+#
+# [*admin_workers*]
+#   (optional) The number of worker processes to serve the admin WSGI application.
+#   Defaults to max($::processorcount, 2)
+#
+# [*public_workers*]
+#   (optional) The number of worker processes to serve the public WSGI application.
+#   Defaults to max($::processorcount, 2)
+#
+# [*sync_db*]
+#   (Optional) Run db sync on the node.
+#   Defaults to true
+#
+# [*enable_fernet_setup*]
+#   (Optional) Setup keystone for fernet tokens. This is typically only
+#   run on a single node, then the keys are replicated to the other nodes
+#   in a cluster. You would typically also pair this with a fernet token
+#   provider setting.
+#   Defaults to false
+#
+# [*fernet_key_repository*]
+#   (Optional) Location for the fernet key repository. This value must
+#   be set if enable_fernet_setup is set to true.
+#   Defaults to '/etc/keystone/fernet-keys'
+#
+# [*fernet_max_active_keys*]
+#   (Optional) Number of maximum active Fernet keys. Integer > 0.
+#   Defaults to undef
 #
 # == Dependencies
 #  None
 class keystone(
   $admin_token,
   $package_ensure         = 'present',
-  $bind_host              = false,
+  $client_package_ensure  = 'present',
   $public_bind_host       = '0.0.0.0',
   $admin_bind_host        = '0.0.0.0',
   $public_port            = '5000',
   $admin_port             = '35357',
-  $compute_port           = '8774',
   $verbose                = false,
   $debug                  = false,
   $log_dir                = '/var/log/keystone',
@@ -292,10 +409,10 @@ class keystone(
   $catalog_type           = 'sql',
   $catalog_driver         = false,
   $catalog_template_file  = '/etc/keystone/default_catalog.templates',
-  $token_format           = false,
   $token_provider         = 'keystone.token.providers.uuid.Provider',
   $token_driver           = 'keystone.token.persistence.backends.sql.Token',
   $token_expiration       = 3600,
+  $revoke_driver          = 'keystone.contrib.revoke.backends.sql.Revoke',
   $public_endpoint        = false,
   $admin_endpoint         = false,
   $enable_ssl             = false,
@@ -306,6 +423,7 @@ class keystone(
   $ssl_cert_subject       = '/C=US/ST=Unset/L=Unset/O=Unset/CN=localhost',
   $cache_dir              = '/var/cache/keystone',
   $memcache_servers       = false,
+  $manage_service         = true,
   $cache_backend          = 'keystone.common.cache.noop',
   $cache_backend_argument = undef,
   $debug_cache_backend    = false,
@@ -333,17 +451,25 @@ class keystone(
   $kombu_ssl_version      = 'TLSv1',
   $notification_driver    = false,
   $notification_topics    = false,
+  $notification_format    = undef,
   $control_exchange       = false,
   $validate_service       = false,
   $validate_insecure      = false,
   $validate_auth_url      = false,
   $validate_cacert        = undef,
+  $paste_config           = $::keystone::params::paste_config,
   $service_provider       = $::keystone::params::service_provider,
-  $service_name           = 'keystone',
+  $service_name           = $::keystone::params::service_name,
+  $max_token_size         = undef,
+  $admin_workers          = max($::processorcount, 2),
+  $public_workers         = max($::processorcount, 2),
+  $sync_db                = true,
+  $enable_fernet_setup    = false,
+  $fernet_key_repository  = '/etc/keystone/fernet-keys',
+  $fernet_max_active_keys = undef,
   # DEPRECATED PARAMETERS
   $mysql_module           = undef,
-  $sql_connection         = undef,
-  $idle_timeout           = undef,
+  $compute_port           = undef,
 ) inherits keystone::params {
 
   if ! $catalog_driver {
@@ -354,20 +480,6 @@ class keystone(
     warning('The mysql_module parameter is deprecated. The latest 2.x mysql module will be used.')
   }
 
-  if $sql_connection {
-    warning('The sql_connection parameter is deprecated, use database_connection instead.')
-    $database_connection_real = $sql_connection
-  } else {
-    $database_connection_real = $database_connection
-  }
-
-  if $idle_timeout {
-    warning('The idle_timeout parameter is deprecated, use database_idle_timeout instead.')
-    $database_idle_timeout_real = $idle_timeout
-  } else {
-    $database_idle_timeout_real = $database_idle_timeout
-  }
-
   if ($admin_endpoint and 'v2.0' in $admin_endpoint) {
     warning('Version string /v2.0/ should not be included in keystone::admin_endpoint')
   }
@@ -391,6 +503,8 @@ class keystone(
   File['/etc/keystone/keystone.conf'] -> Keystone_config<||> ~> Service[$service_name]
   Keystone_config<||> ~> Exec<| title == 'keystone-manage db_sync'|>
   Keystone_config<||> ~> Exec<| title == 'keystone-manage pki_setup'|>
+  Keystone_config<||> ~> Exec<| title == 'keystone-manage fernet_setup'|>
+
   include ::keystone::params
 
   package { 'keystone':
@@ -398,10 +512,12 @@ class keystone(
     name   => $::keystone::params::package_name,
     tag    => 'openstack',
   }
-  # TODO: Move this to openstacklib::openstackclient in Kilo
-  package { 'python-openstackclient':
-    ensure => present,
-    tag    => 'openstack',
+  if $client_package_ensure == 'present' {
+    include '::openstacklib::openstackclient'
+  } else {
+    class { '::openstacklib::openstackclient':
+      package_ensure => $client_package_ensure,
+    }
   }
 
   group { 'keystone':
@@ -435,27 +551,27 @@ class keystone(
     notify  => Service[$service_name],
   }
 
-  if $bind_host {
-    warning('The bind_host parameter is deprecated, use public_bind_host and admin_bind_host instead.')
-    $public_bind_host_real = $bind_host
-    $admin_bind_host_real  = $bind_host
-  } else {
-    $public_bind_host_real = $public_bind_host
-    $admin_bind_host_real  = $admin_bind_host
-  }
-
-  # default config
   keystone_config {
     'DEFAULT/admin_token':      value => $admin_token, secret => true;
-    'DEFAULT/public_bind_host': value => $public_bind_host_real;
-    'DEFAULT/admin_bind_host':  value => $admin_bind_host_real;
+    'DEFAULT/public_bind_host': value => $public_bind_host;
+    'DEFAULT/admin_bind_host':  value => $admin_bind_host;
     'DEFAULT/public_port':      value => $public_port;
     'DEFAULT/admin_port':       value => $admin_port;
-    'DEFAULT/compute_port':     value => $compute_port;
     'DEFAULT/verbose':          value => $verbose;
     'DEFAULT/debug':            value => $debug;
   }
 
+  if $compute_port {
+    warning('The compute_port parameter is deprecated and will be removed in L')
+    keystone_config {
+      'DEFAULT/compute_port': value => $compute_port;
+    }
+  } else {
+    keystone_config {
+      'DEFAULT/compute_port': ensure => absent;
+    }
+  }
+
   # Endpoint configuration
   if $public_endpoint {
     keystone_config {
@@ -489,6 +605,16 @@ class keystone(
     'token/expiration': value => $token_expiration;
   }
 
+  if $revoke_driver {
+    keystone_config {
+      'revoke/driver':    value => $revoke_driver;
+    }
+  } else {
+    keystone_config {
+      'revoke/driver':    ensure => absent;
+    }
+  }
+
   # ssl config
   if ($enable_ssl) {
     keystone_config {
@@ -505,15 +631,15 @@ class keystone(
     }
   }
 
-  if($database_connection_real =~ /mysql:\/\/\S+:\S+@\S+\/\S+/) {
+  if($database_connection =~ /mysql:\/\/\S+:\S+@\S+\/\S+/) {
     require 'mysql::bindings'
     require 'mysql::bindings::python'
-  } elsif($database_connection_real =~ /postgresql:\/\/\S+:\S+@\S+\/\S+/) {
+  } elsif($database_connection =~ /postgresql:\/\/\S+:\S+@\S+\/\S+/) {
 
-  } elsif($database_connection_real =~ /sqlite:\/\//) {
+  } elsif($database_connection =~ /sqlite:\/\//) {
 
   } else {
-    fail("Invalid db connection ${database_connection_real}")
+    fail("Invalid db connection ${database_connection}")
   }
 
   # memcache connection config
@@ -550,8 +676,8 @@ class keystone(
 
   # db connection config
   keystone_config {
-    'database/connection':   value => $database_connection_real, secret => true;
-    'database/idle_timeout': value => $database_idle_timeout_real;
+    'database/connection':   value => $database_connection, secret => true;
+    'database/idle_timeout': value => $database_idle_timeout;
   }
 
   # configure based on the catalog backend
@@ -570,13 +696,6 @@ class keystone(
     'catalog/template_file': value => $catalog_template_file;
   }
 
-  if $token_format {
-    warning('token_format parameter is deprecated. Use token_provider instead.')
-  }
-
-  # remove the old format in case of an upgrade
-  keystone_config { 'signing/token_format': ensure => absent }
-
   # Set the signing key/cert configuration values.
   keystone_config {
     'signing/certfile':     value => $signing_certfile;
@@ -607,12 +726,12 @@ class keystone(
     }
   }
 
-  if ($token_format == false and $token_provider == 'keystone.token.providers.pki.Provider') or $token_format == 'PKI' {
-    keystone_config { 'token/provider': value => 'keystone.token.providers.pki.Provider' }
-  } elsif $token_format == 'UUID' {
-    keystone_config { 'token/provider': value => 'keystone.token.providers.uuid.Provider' }
+  keystone_config { 'token/provider': value => $token_provider }
+
+  if $max_token_size {
+    keystone_config { 'DEFAULT/max_token_size': value => $max_token_size }
   } else {
-    keystone_config { 'token/provider': value => $token_provider }
+    keystone_config { 'DEFAULT/max_token_size': ensure => absent }
   }
 
   if $notification_driver {
@@ -625,6 +744,11 @@ class keystone(
   } else {
     keystone_config { 'DEFAULT/notification_topics': ensure => absent }
   }
+  if $notification_format {
+    keystone_config { 'DEFAULT/notification_format': value => $notification_format }
+  } else {
+    keystone_config { 'DEFAULT/notification_format': ensure => absent }
+  }
   if $control_exchange {
     keystone_config { 'DEFAULT/control_exchange': value => $control_exchange }
   } else {
@@ -664,13 +788,22 @@ class keystone(
     }
   }
 
-  if $enabled {
-    $service_ensure = 'running'
+  keystone_config {
+    'DEFAULT/admin_workers':  value => $admin_workers;
+    'DEFAULT/public_workers': value => $public_workers;
+  }
+
+  if $manage_service {
+    if $enabled {
+      $service_ensure = 'running'
+    } else {
+      $service_ensure = 'stopped'
+    }
   } else {
-    $service_ensure = 'stopped'
+    warning('Execution of db_sync does not depend on $enabled anymore. Please use sync_db instead.')
   }
 
-  if $service_name == 'keystone' {
+  if $service_name == $::keystone::params::service_name {
     if $validate_service {
       if $validate_auth_url {
         $v_auth_url = $validate_auth_url
@@ -678,9 +811,9 @@ class keystone(
         $v_auth_url = $admin_endpoint
       }
 
-      class { 'keystone::service':
+      class { '::keystone::service':
         ensure         => $service_ensure,
-        service_name   => $::keystone::params::service_name,
+        service_name   => $service_name,
         enable         => $enabled,
         hasstatus      => true,
         hasrestart     => true,
@@ -692,9 +825,9 @@ class keystone(
         cacert         => $validate_cacert,
       }
     } else {
-      class { 'keystone::service':
+      class { '::keystone::service':
         ensure       => $service_ensure,
-        service_name => $::keystone::params::service_name,
+        service_name => $service_name,
         enable       => $enabled,
         hasstatus    => true,
         hasrestart   => true,
@@ -702,9 +835,19 @@ class keystone(
         validate     => false,
       }
     }
+  } elsif $service_name == 'httpd' {
+    class { '::keystone::service':
+      ensure       => 'stopped',
+      service_name => $::keystone::params::service_name,
+      enable       => false,
+      provider     => $service_provider,
+      validate     => false,
+    }
+  } else {
+    fail('Invalid service_name. Either keystone/openstack-keystone for running as a standalone service, or httpd for being run by a httpd server')
   }
 
-  if $enabled {
+  if $sync_db {
     include ::keystone::db::sync
     Class['::keystone::db::sync'] ~> Service[$service_name]
   }
@@ -740,4 +883,48 @@ class keystone(
     }
   }
 
+  if $paste_config {
+    keystone_config {
+        'paste_deploy/config_file':   value => $paste_config;
+    }
+  } else {
+    keystone_config {
+        'paste_deploy/config_file':   ensure => absent;
+    }
+  }
+
+  # Fernet tokens support
+  if $enable_fernet_setup {
+    validate_string($fernet_key_repository)
+
+    exec { 'keystone-manage fernet_setup':
+      path        => '/usr/bin',
+      user        => 'keystone',
+      refreshonly => true,
+      creates     => "${fernet_key_repository}/0",
+      notify      => Service[$service_name],
+      subscribe   => [Package['keystone'], Keystone_config['fernet_tokens/key_repository']],
+    }
+  }
+
+  if $fernet_key_repository {
+    keystone_config {
+        'fernet_tokens/key_repository':   value => $fernet_key_repository;
+    }
+  } else {
+    keystone_config {
+        'fernet_tokens/key_repository':   ensure => absent;
+    }
+  }
+
+  if $fernet_max_active_keys {
+    keystone_config {
+        'fernet_tokens/max_active_keys':   value => $fernet_max_active_keys;
+    }
+  } else {
+    keystone_config {
+        'fernet_tokens/max_active_keys':   ensure => absent;
+    }
+  }
+
 }
index 96ec8cd0a7a58f1c453dc902325fb3cdf6ac84cf..05428e971bdb3b28272032d6094b75936d15c991 100644 (file)
@@ -1,6 +1,380 @@
+# == class: keystone::ldap
 #
 # Implements ldap configuration for keystone.
 #
+# === parameters:
+#
+# [*url*]
+#   URL for connecting to the LDAP server. (string value)
+#   Defaults to 'undef'
+#
+# [*user*]
+#   User BindDN to query the LDAP server. (string value)
+#   Defaults to 'undef'
+#
+# [*password*]
+#   Password for the BindDN to query the LDAP server. (string value)
+#   Defaults to 'undef'
+#
+# [*suffix*]
+#   LDAP server suffix (string value)
+#   Defaults to 'undef'
+#
+# [*query_scope*]
+#   The LDAP scope for queries, this can be either "one"
+#   (onelevel/singleLevel) or "sub" (subtree/wholeSubtree). (string value)
+#   Defaults to 'undef'
+#
+# [*page_size*]
+#   Maximum results per page; a value of zero ("0") disables paging. (integer value)
+#   Defaults to 'undef'
+#
+# [*user_tree_dn*]
+#   Search base for users. (string value)
+#   Defaults to 'undef'
+#
+# [*user_filter*]
+#   LDAP search filter for users. (string value)
+#   Defaults to 'undef'
+#
+# [*user_objectclass*]
+#   LDAP objectclass for users. (string value)
+#   Defaults to 'undef'
+#
+# [*user_id_attribute*]
+#   LDAP attribute mapped to user id. WARNING: must not be a multivalued attribute. (string value)
+#   Defaults to 'undef'
+#
+# [*user_name_attribute*]
+#   LDAP attribute mapped to user name. (string value)
+#   Defaults to 'undef'
+#
+# [*user_mail_attribute*]
+#   LDAP attribute mapped to user email. (string value)
+#
+# [*user_enabled_attribute*]
+#   LDAP attribute mapped to user enabled flag. (string value)
+#   Defaults to 'undef'
+#
+# [*user_enabled_mask*]
+#   Bitmask integer to indicate the bit that the enabled value is stored in if
+#   the LDAP server represents "enabled" as a bit on an integer rather than a
+#   boolean. A value of "0" indicates the mask is not used. If this is not set
+#   to "0" the typical value is "2". This is typically used when
+#   "user_enabled_attribute = userAccountControl". (integer value)
+#   Defaults to 'undef'
+#
+# [*user_enabled_default*]
+#   Default value to enable users. This should match an appropriate int value
+#   if the LDAP server uses non-boolean (bitmask) values to indicate if a user
+#   is enabled or disabled. If this is not set to "True" the typical value is
+#   "512". This is typically used when "user_enabled_attribute =
+#   userAccountControl". (string value)
+#   Defaults to 'undef'
+#
+# [*user_enabled_invert*]
+#   Invert the meaning of the boolean enabled values. Some LDAP servers use a
+#   boolean lock attribute where "true" means an account is disabled. Setting
+#   "user_enabled_invert = true" will allow these lock attributes to be used.
+#   This setting will have no effect if "user_enabled_mask" or
+#   "user_enabled_emulation" settings are in use. (boolean value)
+#   Defaults to 'undef'
+#
+# [*user_attribute_ignore*]
+#   List of attributes stripped off the user on update. (list value)
+#   Defaults to 'undef'
+#
+# [*user_default_project_id_attribute*]
+#   LDAP attribute mapped to default_project_id for users. (string value)
+#   Defaults to 'undef'
+#
+# [*user_allow_create*]
+#   Allow user creation in LDAP backend. (boolean value)
+#   Defaults to 'undef'
+#
+# [*user_allow_update*]
+#   Allow user updates in LDAP backend. (boolean value)
+#   Defaults to 'undef'
+#
+# [*user_allow_delete*]
+#   Allow user deletion in LDAP backend. (boolean value)
+#   Defaults to 'undef'
+#
+# [*user_pass_attribute*]
+#   LDAP attribute mapped to password. (string value)
+#   Defaults to 'undef'
+#
+# [*user_enabled_emulation*]
+#   If true, Keystone uses an alternative method to determine if
+#   a user is enabled or not by checking if they are a member of
+#   the "user_enabled_emulation_dn" group. (boolean value)
+#   Defaults to 'undef'
+#
+# [*user_enabled_emulation_dn*]
+#   DN of the group entry to hold enabled users when using enabled emulation.
+#   (string value)
+#   Defaults to 'undef'
+#
+# [*user_additional_attribute_mapping*]
+#   List of additional LDAP attributes used for mapping
+#   additional attribute mappings for users. Attribute mapping
+#   format is <ldap_attr>:<user_attr>, where ldap_attr is the
+#   attribute in the LDAP entry and user_attr is the Identity
+#   API attribute. (list value)
+#   Defaults to 'undef'
+#
+# [*project_tree_dn*]
+#   Search base for projects (string value)
+#   Defaults to 'undef'
+#
+# [*project_filter*]
+#   LDAP search filter for projects. (string value)
+#   Defaults to 'undef'
+#
+# [*project_objectclass*]
+#   LDAP objectclass for projects. (string value)
+#   Defaults to 'undef'
+#
+# [*project_id_attribute*]
+#   LDAP attribute mapped to project id. (string value)
+#   Defaults to 'undef'
+#
+# [*project_member_attribute*]
+#   LDAP attribute mapped to project membership for user. (string value)
+#   Defaults to 'undef'
+#
+# [*project_name_attribute*]
+#   LDAP attribute mapped to project name. (string value)
+#   Defaults to 'undef'
+#
+# [*project_desc_attribute*]
+#   LDAP attribute mapped to project description. (string value)
+#   Defaults to 'undef'
+#
+# [*project_enabled_attribute*]
+#   LDAP attribute mapped to project enabled. (string value)
+#   Defaults to 'undef'
+#
+# [*project_domain_id_attribute*]
+#   LDAP attribute mapped to project domain_id. (string value)
+#   Defaults to 'undef'
+#
+# [*project_attribute_ignore*]
+#   List of attributes stripped off the project on update. (list value)
+#   Defaults to 'undef'
+#
+# [*project_allow_create*]
+#   Allow project creation in LDAP backend. (boolean value)
+#   Defaults to 'undef'
+#
+# [*project_allow_update*]
+#   Allow project update in LDAP backend. (boolean value)
+#   Defaults to 'undef'
+#
+# [*project_allow_delete*]
+#   Allow project deletion in LDAP backend. (boolean value)
+#   Defaults to 'undef'
+#
+# [*project_enabled_emulation*]
+#   If true, Keystone uses an alternative method to determine if
+#   a project is enabled or not by checking if they are a member
+#   of the "project_enabled_emulation_dn" group. (boolean value)
+#   Defaults to 'undef'
+#
+# [*project_enabled_emulation_dn*]
+#   DN of the group entry to hold enabled projects when using
+#   enabled emulation. (string value)
+#   Defaults to 'undef'
+#
+# [*project_additional_attribute_mapping*]
+#   Additional attribute mappings for projects. Attribute
+#   mapping format is <ldap_attr>:<user_attr>, where ldap_attr
+#   is the attribute in the LDAP entry and user_attr is the
+#   Identity API attribute. (list value)
+#   Defaults to 'undef'
+#
+# [*role_tree_dn*]
+#   Search base for roles. (string value)
+#   Defaults to 'undef'
+#
+# [*role_filter*]
+#   LDAP search filter for roles. (string value)
+#   Defaults to 'undef'
+#
+# [*role_objectclass*]
+#   LDAP objectclass for roles. (string value)
+#   Defaults to 'undef'
+#
+# [*role_id_attribute*]
+#   LDAP attribute mapped to role id. (string value)
+#   Defaults to 'undef'
+#
+# [*role_name_attribute*]
+#   LDAP attribute mapped to role name. (string value)
+#   Defaults to 'undef'
+#
+# [*role_member_attribute*]
+#   LDAP attribute mapped to role membership. (string value)
+#   Defaults to 'undef'
+#
+# [*role_attribute_ignore*]
+#   List of attributes stripped off the role on update. (list value)
+#   Defaults to 'undef'
+#
+# [*role_allow_create*]
+#   Allow role creation in LDAP backend. (boolean value)
+#   Defaults to 'undef'
+#
+# [*role_allow_update*]
+#   Allow role update in LDAP backend. (boolean value)
+#   Defaults to 'undef'
+#
+# [*role_allow_delete*]
+#   Allow role deletion in LDAP backend. (boolean value)
+#   Defaults to 'undef'
+#
+# [*role_additional_attribute_mapping*]
+#   Additional attribute mappings for roles. Attribute mapping
+#   format is <ldap_attr>:<user_attr>, where ldap_attr is the
+#   attribute in the LDAP entry and user_attr is the Identity
+#   API attribute. (list value)
+#   Defaults to 'undef'
+#
+# [*group_tree_dn*]
+#   Search base for groups. (string value)
+#   Defaults to 'undef'
+#
+# [*group_filter*]
+#   LDAP search filter for groups. (string value)
+#   Defaults to 'undef'
+#
+# [*group_objectclass*]
+#   LDAP objectclass for groups. (string value)
+#   Defaults to 'undef'
+#
+# [*group_id_attribute*]
+#   LDAP attribute mapped to group id. (string value)
+#   Defaults to 'undef'
+#
+# [*group_name_attribute*]
+#   LDAP attribute mapped to group name. (string value)
+#   Defaults to 'undef'
+#
+# [*group_member_attribute*]
+#   LDAP attribute mapped to show group membership. (string value)
+#   Defaults to 'undef'
+#
+# [*group_desc_attribute*]
+#   LDAP attribute mapped to group description. (string value)
+#   Defaults to 'undef'
+#
+# [*group_attribute_ignore*]
+#   List of attributes stripped off the group on update. (list value)
+#   Defaults to 'undef'
+#
+# [*group_allow_create*]
+#   Allow group creation in LDAP backend. (boolean value)
+#   Defaults to 'undef'
+#
+# [*group_allow_update*]
+#   Allow group update in LDAP backend. (boolean value)
+#   Defaults to 'undef'
+#
+# [*group_allow_delete*]
+#   Allow group deletion in LDAP backend. (boolean value)
+#   Defaults to 'undef'
+#
+# [*group_additional_attribute_mapping*]
+#   Additional attribute mappings for groups. Attribute mapping
+#   format is <ldap_attr>:<user_attr>, where ldap_attr is the
+#   attribute in the LDAP entry and user_attr is the Identity
+#   API attribute. (list value)
+#   Defaults to 'undef'
+#
+# [*use_tls*]
+#   Enable TLS for communicating with LDAP servers. (boolean value)
+#   Defaults to 'undef'
+#
+# [*tls_cacertfile*]
+#   CA certificate file path for communicating with LDAP servers. (string value)
+#   Defaults to 'undef'
+#
+# [*tls_cacertdir*]
+#   CA certificate directory path for communicating with LDAP servers. (string value)
+#   Defaults to 'undef'
+#
+# [*tls_req_cert*]
+#   Valid options for tls_req_cert are demand, never, and allow. (string value)
+#   Defaults to 'undef'
+#
+# [*identity_driver*]
+#   Identity backend driver. (string value)
+#   Defaults to 'undef'
+#
+# [*credential_driver*]
+#   Credential backend driver. (string value)
+#   Defaults to 'undef'
+#
+# [*assignment_driver*]
+#   Assignment backend driver. (string value)
+#   Defaults to 'undef'
+#
+# [*use_pool*]
+#   Enable LDAP connection pooling. (boolean value)
+#   Defaults to false
+#
+# [*pool_size*]
+#   Connection pool size. (integer value)
+#   Defaults to '10'
+#
+# [*pool_retry_max*]
+#   Maximum count of reconnect trials. (integer value)
+#   Defaults to '3'
+#
+# [*pool_retry_delay*]
+#   Time span in seconds to wait between two reconnect trials. (floating point value)
+#   Defaults to '0.1'
+#
+# [*pool_connection_timeout*]
+#   Connector timeout in seconds. Value -1 indicates indefinite wait for response. (integer value)
+#   Defaults to '-1'
+#
+# [*pool_connection_lifetime*]
+#   Connection lifetime in seconds. (integer value)
+#   Defaults to '600'
+#
+# [*use_auth_pool*]
+#   Enable LDAP connection pooling for end user authentication.
+#   If use_pool is disabled, then this setting is meaningless and is not used at all. (boolean value)
+#   Defaults to false
+#
+# [*auth_pool_size*]
+#   End user auth connection pool size. (integer value)
+#   Defaults to '100'
+#
+# [*auth_pool_connection_lifetime*]
+#   End user auth connection lifetime in seconds. (integer value)
+#   Defaults to '60'
+#
+# === DEPRECATED group/name
+#
+# [*tenant_tree_dn*]
+# [*tenant_filter*]
+# [*tenant_objectclass*]
+# [*tenant_id_attribute*]
+# [*tenant_member_attribute*]
+# [*tenant_name_attribute*]
+# [*tenant_desc_attribute*]
+# [*tenant_enabled_attribute*]
+# [*tenant_domain_id_attribute*]
+# [*tenant_attribute_ignore*]
+# [*tenant_allow_create*]
+# [*tenant_allow_update*]
+# [*tenant_enabled_emulation*]
+# [*tenant_enabled_emulation_dn*]
+# [*tenant_additional_attribute_mapping*]
+# [*tenant_allow_delete*]
+#
 # == Dependencies
 # == Examples
 # == Authors
@@ -99,6 +473,7 @@ class keystone::ldap(
   $tls_req_cert                        = undef,
   $identity_driver                     = undef,
   $assignment_driver                   = undef,
+  $credential_driver                   = undef,
   $use_pool                            = false,
   $pool_size                           = 10,
   $pool_retry_max                      = 3,
@@ -307,6 +682,12 @@ class keystone::ldap(
       }
   }
 
+  if ($credential_driver != undef) {
+      if ! ($credential_driver =~ /^keystone.credential.backends.*Credential$/) {
+          fail('credential driver should be of the form \'keystone.credential.backends.*Credential\'')
+      }
+  }
+
   if ($tls_cacertdir != undef) {
     file { $tls_cacertdir:
       ensure => directory
@@ -392,6 +773,7 @@ class keystone::ldap(
     'ldap/auth_pool_size':                       value => $auth_pool_size;
     'ldap/auth_pool_connection_lifetime':        value => $auth_pool_connection_lifetime;
     'identity/driver':                           value => $identity_driver;
+    'credential/driver':                         value => $credential_driver;
     'assignment/driver':                         value => $assignment_driver;
   }
 }
index f3f0f4d265789d4d97e63af2378923929105c15c..12660caee0797646b8b597a008a934e36cc3d065 100644 (file)
@@ -10,6 +10,7 @@ class keystone::params {
       $service_name                 = 'keystone'
       $keystone_wsgi_script_path    = '/usr/lib/cgi-bin/keystone'
       $python_memcache_package_name = 'python-memcache'
+      $paste_config                 = undef
       case $::operatingsystem {
         'Debian': {
           $service_provider            = undef
@@ -31,6 +32,7 @@ class keystone::params {
       $python_memcache_package_name = 'python-memcached'
       $service_provider             = undef
       $keystone_wsgi_script_source  = '/usr/share/keystone/keystone.wsgi'
+      $paste_config                 = '/usr/share/keystone/keystone-dist-paste.ini'
     }
   }
 }
index 858fd650424392c184374999f39ce6890a3a91ba..32adc63f4333537ad89d109b1c79aa0a39fc72c5 100644 (file)
@@ -1,6 +1,16 @@
+# == Class keystone::python
 #
 # installs client python libraries for keystone
 #
+# === Parameters:
+#
+# [*client_package_name*]
+#   (optional) The name of python keystone client package
+#   Defaults to $keystone::params::client_package_name
+#
+# [*ensure*]
+#   (optional) The state for the keystone client package
+#   Defaults to 'present'
 #
 class keystone::python (
   $client_package_name = $keystone::params::client_package_name,
index 08eaa7f5e5931ea88dbcae7c5f7979393547dcb5..9bbd1b13ae7c5df99feb380ff901b681864b7947 100644 (file)
 # == Parameters:
 #
 # [*password*]
-# Password to create for the service user;
-# string; required
+#   Password to create for the service user;
+#   string; required
 #
 # [*auth_name*]
-# The name of the service user;
-# string; optional; default to the $title of the resource, i.e. 'nova'
+#   The name of the service user;
+#   string; optional; default to the $title of the resource, i.e. 'nova'
 #
 # [*service_name*]
-# Name of the service;
-# string; required
+#   Name of the service;
+#   string; required
 #
 # [*service_type*]
-# Type of the service;
-# string; required
+#   Type of the service;
+#   string; required
 #
 # [*service_description*]
-# Description of the service;
-# string; optional: default to '$name service'
+#   Description of the service;
+#   string; optional: default to '$name service'
 #
 # [*public_url*]
-# Public endpoint URL;
-# string; required
+#   Public endpoint URL;
+#   string; required
 #
 # [*internal_url*]
-# Internal endpoint URL;
-# string; required
+#   Internal endpoint URL;
+#   string; required
 #
 # [*admin_url*]
-# Admin endpoint URL;
-# string; required
+#   Admin endpoint URL;
+#   string; required
 #
 # [*region*]
-# Endpoint region;
-# string; optional: default to 'RegionOne'
+#   Endpoint region;
+#   string; optional: default to 'RegionOne'
 #
 # [*tenant*]
-# Service tenant;
-# string; optional: default to 'services'
+#   Service tenant;
+#   string; optional: default to 'services'
 #
 # [*ignore_default_tenant*]
-# Ignore setting the default tenant value when the user is created.
-# string; optional: default to false
+#   Ignore setting the default tenant value when the user is created.
+#   string; optional: default to false
 #
 # [*roles*]
-# List of roles;
-# string; optional: default to ['admin']
+#   List of roles;
+#   string; optional: default to ['admin']
 #
 # [*domain*]
-# User domain (keystone v3), not implemented yet.
-# string; optional: default to undef
+#   User domain (keystone v3), not implemented yet.
+#   string; optional: default to undef
 #
 # [*email*]
-# Service email;
-# string; optional: default to '$auth_name@localhost'
+#   Service email;
+#   string; optional: default to '$auth_name@localhost'
 #
 # [*configure_endpoint*]
-# Whether to create the endpoint.
-# string; optional: default to True
+#   Whether to create the endpoint.
+#   string; optional: default to True
 #
 # [*configure_user*]
-# Whether to create the user.
-# string; optional: default to True
+#   Whether to create the user.
+#   string; optional: default to True
 #
 # [*configure_user_role*]
-# Whether to create the user role.
-# string; optional: default to True
+#   Whether to create the user role.
+#   string; optional: default to True
 #
 # [*configure_service*]
-# Whether to create the service.
-# string; optional: default to True
+#   Whether to create the service.
+#   string; optional: default to True
 #
 define keystone::resource::service_identity(
   $admin_url             = false,
index 4fd5e097040b9b89fdc1d457c4c023897f0c69c7..aa5abd72fa2ce1fa7fb64a161ba5c43b4da771ac 100644 (file)
@@ -1,3 +1,4 @@
+# == Class: keystone::roles::admin
 #
 # This class implements some reasonable admin defaults for keystone.
 #
@@ -8,18 +9,49 @@
 #   * admin role
 #   * adds admin role to admin user on the "admin" tenant
 #
-# [*Parameters*]
-#
-# [email] The email address for the admin. Required.
-# [password] The admin password. Required.
-# [admin_roles] The list of the roles with admin privileges. Optional. Defaults to ['admin'].
-# [admin_tenant] The name of the tenant to be used for admin privileges. Optional. Defaults to openstack.
-# [admin] Admin user. Optional. Defaults to admin.
-# [ignore_default_tenant] Ignore setting the default tenant value when the user is created. Optional. Defaults to false.
-# [admin_tenant_desc] Optional. Description for admin tenant, defaults to 'admin tenant'
-# [service_tenant_desc] Optional. Description for admin tenant, defaults to 'Tenant for the openstack services'
-# [configure_user] Optional. Should the admin user be created? Defaults to 'true'.
-# [configure_user_role] Optional. Should the admin role be configured for the admin user? Defaulst to 'true'.
+# === Parameters:
+#
+# [*email*]
+#   The email address for the admin. Required.
+#
+# [*password*]
+#   The admin password. Required.
+#
+# [*admin_roles*]
+#   The list of the roles with admin privileges. Optional.
+#   Defaults to ['admin'].
+#
+# [*admin_tenant*]
+#   The name of the tenant to be used for admin privileges. Optional.
+#   Defaults to openstack.
+#
+# [*service_tenant*]
+#   The name of service keystone tenant. Optional.
+#   Defaults to 'services'.
+#
+# [*admin*]
+#   Admin user. Optional.
+#   Defaults to admin.
+#
+# [*ignore_default_tenant*]
+#   Ignore setting the default tenant value when the user is created. Optional.
+#   Defaults to false.
+#
+# [*admin_tenant_desc*]
+#   Optional. Description for admin tenant,
+#   Defaults to 'admin tenant'
+#
+# [*service_tenant_desc*]
+#   Optional. Description for admin tenant,
+#   Defaults to 'Tenant for the openstack services'
+#
+# [*configure_user*]
+#   Optional. Should the admin user be created?
+#   Defaults to 'true'.
+#
+# [*configure_user_role*]
+#   Optional. Should the admin role be configured for the admin user?
+#   Defaulst to 'true'.
 #
 # == Dependencies
 # == Examples
index 63c148d3b958d13ec2979f581d324ca44add92eb..46312144ab897eda7188b68794406070d06a66ae 100644 (file)
@@ -9,63 +9,62 @@
 # === Parameters
 #
 # [*ensure*]
-# (optional) The desired state of the keystone service
-# Defaults to 'running'
+#   (optional) The desired state of the keystone service
+#   Defaults to undef
 #
 # [*service_name*]
-# (optional) The name of the keystone service
-# Defaults to $::keystone::params::service_name
+#   (optional) The name of the keystone service
+#   Defaults to $::keystone::params::service_name
 #
 # [*enable*]
-# (optional) Whether to enable the keystone service
-# Defaults to true
+#   (optional) Whether to enable the keystone service
+#   Defaults to true
 #
 # [*hasstatus*]
-# (optional) Whether the keystone service has status
-# Defaults to true
+#   (optional) Whether the keystone service has status
+#   Defaults to true
 #
 # [*hasrestart*]
-# (optional) Whether the keystone service has restart
-# Defaults to true
+#   (optional) Whether the keystone service has restart
+#   Defaults to true
 #
 # [*provider*]
-# (optional) Provider for keystone service
-# Defaults to $::keystone::params::service_provider
+#   (optional) Provider for keystone service
+#   Defaults to $::keystone::params::service_provider
 #
 # [*validate*]
-# (optional) Whether to validate the service is working
-# after any service refreshes
-# Defaults to false
+#   (optional) Whether to validate the service is working after any service refreshes
+#   Defaults to false
 #
 # [*admin_token*]
-# (optional) The admin token to use for validation
-# Defaults to undef
+#   (optional) The admin token to use for validation
+#   Defaults to undef
 #
 # [*admin_endpoint*]
-# (optional) The admin endpont to use for validation
-# Defaults to 'http://localhost:35357/v2.0'
+#   (optional) The admin endpont to use for validation
+#   Defaults to 'http://localhost:35357/v2.0'
 #
 # [*retries*]
-# (optional) Number of times to retry validation
-# Defaults to 10
+#   (optional) Number of times to retry validation
+#   Defaults to 10
 #
 # [*delay*]
-# (optional) Number of seconds between validation attempts
-# Defaults to 2
+#   (optional) Number of seconds between validation attempts
+#   Defaults to 2
 #
 # [*insecure*]
-# (optional) Whether to validate keystone connections
-# using the --insecure option with keystone client.
-# Defaults to false
+#   (optional) Whether to validate keystone connections
+#   using the --insecure option with keystone client.
+#   Defaults to false
 #
 # [*cacert*]
-# (optional) Whether to validate keystone connections
-# using the specified argument with the --os-cacert option
-# with keystone client.
-# Defaults to undef
+#   (optional) Whether to validate keystone connections
+#   using the specified argument with the --os-cacert option
+#   with keystone client.
+#   Defaults to undef
 #
 class keystone::service(
-  $ensure         = 'running',
+  $ensure         = undef,
   $service_name   = $::keystone::params::service_name,
   $enable         = true,
   $hasstatus      = true,
@@ -79,7 +78,7 @@ class keystone::service(
   $insecure       = false,
   $cacert         = undef,
 ) {
-  include keystone::params
+  include ::keystone::params
 
   service { 'keystone':
     ensure     => $ensure,
@@ -103,16 +102,16 @@ class keystone::service(
   }
 
   if $validate and $admin_token and $admin_endpoint {
-    $cmd = "keystone --os-endpoint ${admin_endpoint} --os-token ${admin_token} ${insecure_s} ${cacert_s} user-list"
+    $cmd = "openstack --os-auth-url ${admin_endpoint} --os-token ${admin_token} ${insecure_s} ${cacert_s} user list"
     $catch = 'name'
     exec { 'validate_keystone_connection':
-      path          => '/usr/bin:/bin:/usr/sbin:/sbin',
-      provider      => shell,
-      command       => $cmd,
-      subscribe     => Service['keystone'],
-      refreshonly   => true,
-      tries         => $retries,
-      try_sleep     => $delay
+      path        => '/usr/bin:/bin:/usr/sbin:/sbin',
+      provider    => shell,
+      command     => $cmd,
+      subscribe   => Service['keystone'],
+      refreshonly => true,
+      tries       => $retries,
+      try_sleep   => $delay
     }
 
     Exec['validate_keystone_connection'] -> Keystone_user<||>
index 3192821b9102041da04772baa144dbf2bc55c151..66e28aacc14078183f2c25693370add14e881a1a 100644 (file)
@@ -1,7 +1,6 @@
 #
 # Class to serve keystone with apache mod_wsgi in place of keystone service
 #
-#
 # Serving keystone from apache is the recommended way to go for production
 # systems as the current keystone implementation is not multi-processor aware,
 # thus limiting the performance for concurrent accesses.
 #     Optional. Defaults to 1
 #
 #   [*ssl_cert*]
+#     (optional) Path to SSL certificate
+#     Default to apache::vhost 'ssl_*' defaults.
+#
 #   [*ssl_key*]
+#     (optional) Path to SSL key
+#     Default to apache::vhost 'ssl_*' defaults.
+#
 #   [*ssl_chain*]
+#     (optional) SSL chain
+#     Default to apache::vhost 'ssl_*' defaults.
+#
 #   [*ssl_ca*]
+#     (optional) Path to SSL certificate authority
+#     Default to apache::vhost 'ssl_*' defaults.
+#
 #   [*ssl_crl_path*]
+#     (optional) Path to SSL certificate revocation list
+#     Default to apache::vhost 'ssl_*' defaults.
+#
 #   [*ssl_crl*]
+#     (optional) SSL certificate revocation list name
+#     Default to apache::vhost 'ssl_*' defaults.
+#
 #   [*ssl_certs_dir*]
 #     apache::vhost ssl parameters.
 #     Optional. Default to apache::vhost 'ssl_*' defaults.
 #
+#   [*priority*]
+#     (optional) The priority for the vhost.
+#     Defaults to '10'
+#
+#   [*threads*]
+#     (optional) The number of threads for the vhost.
+#     Defaults to $::processorcount
+#
+#   [*wsgi_script_ensure*]
+#     (optional) File ensure parameter for wsgi scripts.
+#     Defaults to 'file'.
+#
+#   [*wsgi_script_source*]
+#     (optional) Wsgi script source.
+#     Defaults to undef.
+#
 # == Dependencies
 #
 #   requires Class['apache'] & Class['keystone']
 #   Copyright 2013 eNovance <licensing@enovance.com>
 #
 class keystone::wsgi::apache (
-  $servername    = $::fqdn,
-  $public_port   = 5000,
-  $admin_port    = 35357,
-  $bind_host     = undef,
-  $public_path   = '/',
-  $admin_path    = '/',
-  $ssl           = true,
-  $workers       = 1,
-  $ssl_cert      = undef,
-  $ssl_key       = undef,
-  $ssl_chain     = undef,
-  $ssl_ca        = undef,
-  $ssl_crl_path  = undef,
-  $ssl_crl       = undef,
-  $ssl_certs_dir = undef,
-  $threads       = $::processorcount,
-  $priority      = '10',
+  $servername         = $::fqdn,
+  $public_port        = 5000,
+  $admin_port         = 35357,
+  $bind_host          = undef,
+  $public_path        = '/',
+  $admin_path         = '/',
+  $ssl                = true,
+  $workers            = 1,
+  $ssl_cert           = undef,
+  $ssl_key            = undef,
+  $ssl_chain          = undef,
+  $ssl_ca             = undef,
+  $ssl_crl_path       = undef,
+  $ssl_crl            = undef,
+  $ssl_certs_dir      = undef,
+  $threads            = $::processorcount,
+  $priority           = '10',
+  $wsgi_script_ensure = 'file',
+  $wsgi_script_source = undef,
 ) {
 
   include ::keystone::params
@@ -134,28 +169,35 @@ class keystone::wsgi::apache (
     require => Package['httpd'],
   }
 
-  file { 'keystone_wsgi_admin':
-    ensure  => file,
-    path    => "${::keystone::params::keystone_wsgi_script_path}/admin",
-    source  => $::keystone::params::keystone_wsgi_script_source,
-    owner   => 'keystone',
-    group   => 'keystone',
-    mode    => '0644',
-    # source file provided by keystone package
-    require => [File[$::keystone::params::keystone_wsgi_script_path], Package['keystone']],
+  $wsgi_files = {
+    'keystone_wsgi_admin' => {
+      'path' => "${::keystone::params::keystone_wsgi_script_path}/admin",
+    },
+    'keystone_wsgi_main'  => {
+      'path' => "${::keystone::params::keystone_wsgi_script_path}/main",
+    },
   }
 
-  file { 'keystone_wsgi_main':
-    ensure  => file,
-    path    => "${::keystone::params::keystone_wsgi_script_path}/main",
-    source  => $::keystone::params::keystone_wsgi_script_source,
-    owner   => 'keystone',
-    group   => 'keystone',
-    mode    => '0644',
-    # source file provided by keystone package
-    require => [File[$::keystone::params::keystone_wsgi_script_path], Package['keystone']],
+  $wsgi_file_defaults = {
+    'ensure'  => $wsgi_script_ensure,
+    'owner'   => 'keystone',
+    'group'   => 'keystone',
+    'mode'    => '0644',
+    'require' => [File[$::keystone::params::keystone_wsgi_script_path], Package['keystone']],
   }
 
+  $wsgi_script_source_real = $wsgi_script_source ? {
+    default => $wsgi_script_source,
+    undef   => $::keystone::params::keystone_wsgi_script_source,
+  }
+
+  case $wsgi_script_ensure {
+    'link':  { $wsgi_file_source = { 'target' => $wsgi_script_source_real } }
+    default: { $wsgi_file_source = { 'source' => $wsgi_script_source_real } }
+  }
+
+  create_resources('file', $wsgi_files, merge($wsgi_file_defaults, $wsgi_file_source))
+
   $wsgi_daemon_process_options_main = {
     user         => 'keystone',
     group        => 'keystone',
index 6f40ac9651c0a08bc41995a5e42d409565da3924..77e23afd4e9d77ab8448524b0ddf42fdce9323af 100644 (file)
@@ -7,49 +7,33 @@
   "source": "git://github.com/openstack/puppet-keystone.git",
   "project_page": "https://launchpad.net/puppet-keystone",
   "issues_url": "https://bugs.launchpad.net/puppet-keystone",
-  "dependencies": [
-    {"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"}
-  ],
   "requirements": [
-    {
-      "name": "pe",
-      "version_requirement": "3.x"
-    },
-    {
-      "name": "puppet",
-      "version_requirement": "3.x"
-    }
+    { "name": "pe","version_requirement": "3.x" },
+    { "name": "puppet","version_requirement": "3.x" }
   ],
   "operatingsystem_support": [
     {
       "operatingsystem": "Debian",
-      "operatingsystemrelease": [
-        "7"
-      ]
+      "operatingsystemrelease": ["7"]
     },
     {
       "operatingsystem": "Fedora",
-      "operatingsystemrelease": [
-        "20"
-      ]
+      "operatingsystemrelease": ["20"]
     },
     {
       "operatingsystem": "RedHat",
-      "operatingsystemrelease": [
-        "6.5",
-        "7"
-      ]
+      "operatingsystemrelease": ["6.5","7"]
     },
     {
       "operatingsystem": "Ubuntu",
-      "operatingsystemrelease": [
-        "12.04",
-        "14.04"
-      ]
+      "operatingsystemrelease": ["12.04","14.04"]
     }
   ],
-  "description": "Installs and configures OpenStack Keystone (Identity)."
+  "description": "Installs and configures OpenStack Keystone (Identity).",
+  "dependencies": [
+    { "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" }
+  ]
 }
diff --git a/3rdparty/modules/keystone/spec/acceptance/basic_keystone_spec.rb b/3rdparty/modules/keystone/spec/acceptance/basic_keystone_spec.rb
new file mode 100644 (file)
index 0000000..b0fd8d3
--- /dev/null
@@ -0,0 +1,116 @@
+require 'spec_helper_acceptance'
+
+describe 'basic keystone server 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,
+      }
+      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/",
+      }
+      ::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',
+      }
+      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.with('tcp') }
+    end
+
+    describe port(35357) do
+      it { is_expected.to be_listening.with('tcp') }
+    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') }
+    end
+
+    describe 'test keystone user/tenant/service/role/endpoint resources' do
+      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|
+          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|
+          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|
+          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|
+          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|
+          expect(r.stdout).to match(/1234/)
+          expect(r.stderr).to be_empty
+        end
+      end
+    end
+  end
+end
diff --git a/3rdparty/modules/keystone/spec/acceptance/nodesets/default.yml b/3rdparty/modules/keystone/spec/acceptance/nodesets/default.yml
new file mode 100644 (file)
index 0000000..a2c1ecc
--- /dev/null
@@ -0,0 +1,9 @@
+HOSTS:
+  ubuntu-14.04-amd64:
+    roles:
+      - master
+    platform: ubuntu-14.04-amd64
+    hypervisor : none
+    ip: 127.0.0.1
+CONFIG:
+  type: foss
diff --git a/3rdparty/modules/keystone/spec/acceptance/nodesets/nodepool-centos7.yml b/3rdparty/modules/keystone/spec/acceptance/nodesets/nodepool-centos7.yml
new file mode 100644 (file)
index 0000000..575ae67
--- /dev/null
@@ -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/3rdparty/modules/keystone/spec/acceptance/nodesets/nodepool-trusty.yml b/3rdparty/modules/keystone/spec/acceptance/nodesets/nodepool-trusty.yml
new file mode 100644 (file)
index 0000000..a95d9f3
--- /dev/null
@@ -0,0 +1,10 @@
+HOSTS:
+  ubuntu-14.04-amd64:
+    roles:
+      - master
+    platform: ubuntu-14.04-amd64
+    hypervisor : none
+    ip: 127.0.0.1
+CONFIG:
+  type: foss
+  set_env: false
index 5ed6f6bb2d152fc9697625015bbcb5443ad1e991..2e58fad52ac2004d64673649eb27104d3ed6c52e 100644 (file)
@@ -3,7 +3,7 @@ require 'spec_helper'
 describe 'keystone::client' do
 
   describe "with default parameters" do
-    it { should contain_package('python-keystoneclient').with(
+    it { is_expected.to contain_package('python-keystoneclient').with(
         'ensure' => 'present',
         'tag'    => 'openstack'
     ) }
@@ -14,7 +14,7 @@ describe 'keystone::client' do
       {:ensure => '2013.1'}
     end
 
-    it { should contain_package('python-keystoneclient').with(
+    it { is_expected.to contain_package('python-keystoneclient').with(
         'ensure' => '2013.1',
         'tag'    => 'openstack'
     ) }
index 597042b363c6b70807f9a5d3e2aa0e230bde6fa0..88e1fd519347593f99035c70676419d89c556faf 100644 (file)
@@ -8,7 +8,7 @@ describe 'keystone::cron::token_flush' do
 
   describe 'with default parameters' do
     it 'configures a cron' do
-      should contain_cron('keystone-manage token_flush').with(
+      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',
         :environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh',
@@ -30,7 +30,7 @@ describe 'keystone::cron::token_flush' do
     end
 
     it 'configures a cron with delay' do
-      should contain_cron('keystone-manage token_flush').with(
+      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',
         :environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh',
@@ -52,7 +52,7 @@ describe 'keystone::cron::token_flush' do
     end
 
     it 'configures a cron with delay' do
-      should contain_cron('keystone-manage token_flush').with(
+      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',
         :environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh',
index f20ea9b2c071bb1f3d970b94a5fee9f6231f8e82..f032aa99f6adbde345470f91da8be8e0d3417bad 100644 (file)
@@ -20,12 +20,13 @@ describe 'keystone::db::mysql' do
   end
 
   describe 'with only required params' do
-    it { should contain_openstacklib__db__mysql('keystone').with(
+    it { is_expected.to contain_openstacklib__db__mysql('keystone').with(
       'user'          => 'keystone',
       'password_hash' => '*B552157B14BCEDDCEAA06767A012F31BDAA9CE3D',
       'dbname'        => 'keystone',
       'host'          => '127.0.0.1',
-      'charset'       => 'utf8'
+      'charset'       => 'utf8',
+      :collate        => 'utf8_general_ci',
     )}
   end
 
index 7efe94619d914facb9a8d0189c064910ae446f39..ecdad5a28fc168b213773ba681236e01b2279737 100644 (file)
@@ -3,24 +3,56 @@ require 'spec_helper'
 describe 'keystone::db::postgresql' do
 
   let :req_params do
-    {:password => 'pw'}
+    { :password => 'pw' }
   end
 
-  let :facts do
-    {
-      :postgres_default_version => '8.4',
-      :osfamily => 'RedHat',
-    }
+  let :pre_condition do
+    'include postgresql::server'
   end
 
-  describe 'with only required params' do
-    let :params do
-      req_params
+  context 'on a RedHat osfamily' do
+    let :facts do
+      {
+        :osfamily                 => 'RedHat',
+        :operatingsystemrelease   => '7.0',
+        :concat_basedir => '/var/lib/puppet/concat'
+      }
     end
-    it { should contain_postgresql__db('keystone').with(
-      :user         => 'keystone',
-      :password     => 'pw'
-     ) }
+
+    context 'with only required parameters' do
+      let :params do
+        req_params
+      end
+
+      it { is_expected.to contain_postgresql__server__db('keystone').with(
+        :user     => 'keystone',
+        :password => 'md5c530c33636c58ae83ca933f39319273e'
+      )}
+    end
+
+  end
+
+  context 'on a Debian osfamily' do
+    let :facts do
+      {
+        :operatingsystemrelease => '7.8',
+        :operatingsystem        => 'Debian',
+        :osfamily               => 'Debian',
+        :concat_basedir => '/var/lib/puppet/concat'
+      }
+    end
+
+    context 'with only required parameters' do
+      let :params do
+        req_params
+      end
+
+      it { is_expected.to contain_postgresql__server__db('keystone').with(
+        :user     => 'keystone',
+        :password => 'md5c530c33636c58ae83ca933f39319273e'
+      )}
+    end
+
   end
 
 end
index 61b596abd44f7cb7dfcf6f88fe185a19b3364eb0..217d791f9d624df3754123c29c404609534f8a09 100644 (file)
@@ -2,14 +2,14 @@ require 'spec_helper'
 
 describe 'keystone::endpoint' do
 
-  it { should contain_keystone_service('keystone').with(
+  it { is_expected.to contain_keystone_service('keystone').with(
     :ensure      => 'present',
     :type        => 'identity',
     :description => 'OpenStack Identity Service'
   )}
 
   describe 'with default parameters' do
-    it { should contain_keystone_endpoint('RegionOne/keystone').with(
+    it { is_expected.to contain_keystone_endpoint('RegionOne/keystone').with(
       :ensure       => 'present',
       :public_url   => 'http://127.0.0.1:5000/v2.0',
       :admin_url    => 'http://127.0.0.1:35357/v2.0',
@@ -26,7 +26,7 @@ describe 'keystone::endpoint' do
         :internal_url => 'https://identity-int.some.tld/some/internal/endpoint' }
     end
 
-    it { should contain_keystone_endpoint('RegionOne/keystone').with(
+    it { is_expected.to contain_keystone_endpoint('RegionOne/keystone').with(
       :ensure       => 'present',
       :public_url   => 'https://identity.some.tld/the/main/endpoint/v42.6',
       :admin_url    => 'https://identity-int.some.tld/some/admin/endpoint/v42.6',
@@ -41,59 +41,11 @@ describe 'keystone::endpoint' do
     end
 
     it 'internal_url should default to public_url' do
-      should contain_keystone_endpoint('RegionOne/keystone').with(
+      is_expected.to contain_keystone_endpoint('RegionOne/keystone').with(
         :ensure       => 'present',
         :public_url   => 'https://identity.some.tld/the/main/endpoint/v2.0',
         :internal_url => 'https://identity.some.tld/the/main/endpoint/v2.0'
       )
     end
   end
-
-  describe 'with deprecated parameters' do
-
-    let :params do
-      { :public_address   => '10.0.0.1',
-        :admin_address    => '10.0.0.2',
-        :internal_address => '10.0.0.3',
-        :public_port      => '23456',
-        :admin_port       => '12345',
-        :region           => 'RegionTwo',
-        :version          => 'v3.0' }
-    end
-
-    it { should contain_keystone_endpoint('RegionTwo/keystone').with(
-      :ensure       => 'present',
-      :public_url   => 'http://10.0.0.1:23456/v3.0',
-      :admin_url    => 'http://10.0.0.2:12345/v3.0',
-      :internal_url => 'http://10.0.0.3:23456/v3.0'
-    )}
-
-    describe 'public_address overrides public_url' do
-      let :params do
-        { :public_address => '10.0.0.1',
-          :public_port    => '12345',
-          :public_url     => 'http://10.10.10.10:23456/v3.0' }
-      end
-
-      it { should contain_keystone_endpoint('RegionOne/keystone').with(
-        :ensure     => 'present',
-        :public_url => 'http://10.0.0.1:12345/v2.0'
-      )}
-    end
-  end
-
-  describe 'with overridden deprecated internal_port' do
-
-    let :params do
-      { :internal_port => '12345' }
-    end
-
-    it { should contain_keystone_endpoint('RegionOne/keystone').with(
-      :ensure       => 'present',
-      :public_url   => 'http://127.0.0.1:5000/v2.0',
-      :admin_url    => 'http://127.0.0.1:35357/v2.0',
-      :internal_url => 'http://127.0.0.1:12345/v2.0'
-    )}
-  end
-
 end
index 088526e8697940a6a3956f7d1dbf66a030f3cb39..0d36624c456166129656902d40b37913dba6daa0 100644 (file)
@@ -73,6 +73,7 @@ describe 'keystone::ldap' do
         :tls_cacertfile => '/etc/ssl/certs/ca-certificates.crt',
         :tls_req_cert => 'demand',
         :identity_driver => 'keystone.identity.backends.ldap.Identity',
+        :credential_driver => 'keystone.credential.backends.ldap.Credential',
         :assignment_driver => 'keystone.assignment.backends.ldap.Assignment',
         :use_pool => 'True',
         :pool_size => 20,
@@ -85,104 +86,105 @@ describe 'keystone::ldap' do
         :auth_pool_connection_lifetime => 200,
       }
     end
-    it { should contain_package('python-ldap') }
-    it { should contain_package('python-ldappool') }
+    it { is_expected.to contain_package('python-ldap') }
+    it { is_expected.to contain_package('python-ldappool') }
     it 'should have basic params' do
       # basic params
-      should contain_keystone_config('ldap/url').with_value('ldap://foo')
-      should contain_keystone_config('ldap/user').with_value('cn=foo,dc=example,dc=com')
-      should contain_keystone_config('ldap/password').with_value('abcdefg').with_secret(true)
-      should contain_keystone_config('ldap/suffix').with_value('dc=example,dc=com')
-      should contain_keystone_config('ldap/query_scope').with_value('sub')
-      should contain_keystone_config('ldap/page_size').with_value('50')
+      is_expected.to contain_keystone_config('ldap/url').with_value('ldap://foo')
+      is_expected.to contain_keystone_config('ldap/user').with_value('cn=foo,dc=example,dc=com')
+      is_expected.to contain_keystone_config('ldap/password').with_value('abcdefg').with_secret(true)
+      is_expected.to contain_keystone_config('ldap/suffix').with_value('dc=example,dc=com')
+      is_expected.to contain_keystone_config('ldap/query_scope').with_value('sub')
+      is_expected.to contain_keystone_config('ldap/page_size').with_value('50')
 
       # users
-      should contain_keystone_config('ldap/user_tree_dn').with_value('cn=users,dc=example,dc=com')
-      should contain_keystone_config('ldap/user_filter').with_value('(memberOf=cn=openstack,cn=groups,cn=accounts,dc=example,dc=com)')
-      should contain_keystone_config('ldap/user_objectclass').with_value('inetUser')
-      should contain_keystone_config('ldap/user_id_attribute').with_value('uid')
-      should contain_keystone_config('ldap/user_name_attribute').with_value('cn')
-      should contain_keystone_config('ldap/user_mail_attribute').with_value('mail')
-      should contain_keystone_config('ldap/user_enabled_attribute').with_value('UserAccountControl')
-      should contain_keystone_config('ldap/user_enabled_mask').with_value('2')
-      should contain_keystone_config('ldap/user_enabled_default').with_value('512')
-      should contain_keystone_config('ldap/user_enabled_invert').with_value('False')
-      should contain_keystone_config('ldap/user_attribute_ignore').with_value('')
-      should contain_keystone_config('ldap/user_default_project_id_attribute').with_value('defaultProject')
-      should contain_keystone_config('ldap/user_tree_dn').with_value('cn=users,dc=example,dc=com')
-      should contain_keystone_config('ldap/user_allow_create').with_value('False')
-      should contain_keystone_config('ldap/user_allow_update').with_value('False')
-      should contain_keystone_config('ldap/user_allow_delete').with_value('False')
-      should contain_keystone_config('ldap/user_pass_attribute').with_value('krbPassword')
-      should contain_keystone_config('ldap/user_enabled_emulation').with_value('True')
-      should contain_keystone_config('ldap/user_enabled_emulation_dn').with_value('cn=openstack-enabled,cn=groups,cn=accounts,dc=example,dc=com')
-      should contain_keystone_config('ldap/user_additional_attribute_mapping').with_value('description:name, gecos:name')
+      is_expected.to contain_keystone_config('ldap/user_tree_dn').with_value('cn=users,dc=example,dc=com')
+      is_expected.to contain_keystone_config('ldap/user_filter').with_value('(memberOf=cn=openstack,cn=groups,cn=accounts,dc=example,dc=com)')
+      is_expected.to contain_keystone_config('ldap/user_objectclass').with_value('inetUser')
+      is_expected.to contain_keystone_config('ldap/user_id_attribute').with_value('uid')
+      is_expected.to contain_keystone_config('ldap/user_name_attribute').with_value('cn')
+      is_expected.to contain_keystone_config('ldap/user_mail_attribute').with_value('mail')
+      is_expected.to contain_keystone_config('ldap/user_enabled_attribute').with_value('UserAccountControl')
+      is_expected.to contain_keystone_config('ldap/user_enabled_mask').with_value('2')
+      is_expected.to contain_keystone_config('ldap/user_enabled_default').with_value('512')
+      is_expected.to contain_keystone_config('ldap/user_enabled_invert').with_value('False')
+      is_expected.to contain_keystone_config('ldap/user_attribute_ignore').with_value('')
+      is_expected.to contain_keystone_config('ldap/user_default_project_id_attribute').with_value('defaultProject')
+      is_expected.to contain_keystone_config('ldap/user_tree_dn').with_value('cn=users,dc=example,dc=com')
+      is_expected.to contain_keystone_config('ldap/user_allow_create').with_value('False')
+      is_expected.to contain_keystone_config('ldap/user_allow_update').with_value('False')
+      is_expected.to contain_keystone_config('ldap/user_allow_delete').with_value('False')
+      is_expected.to contain_keystone_config('ldap/user_pass_attribute').with_value('krbPassword')
+      is_expected.to contain_keystone_config('ldap/user_enabled_emulation').with_value('True')
+      is_expected.to contain_keystone_config('ldap/user_enabled_emulation_dn').with_value('cn=openstack-enabled,cn=groups,cn=accounts,dc=example,dc=com')
+      is_expected.to contain_keystone_config('ldap/user_additional_attribute_mapping').with_value('description:name, gecos:name')
 
       # projects/tenants
-      should contain_keystone_config('ldap/project_tree_dn').with_value('ou=projects,ou=openstack,dc=example,dc=com')
-      should contain_keystone_config('ldap/project_filter').with_value('')
-      should contain_keystone_config('ldap/project_objectclass').with_value('organizationalUnit')
-      should contain_keystone_config('ldap/project_id_attribute').with_value('ou')
-      should contain_keystone_config('ldap/project_member_attribute').with_value('member')
-      should contain_keystone_config('ldap/project_desc_attribute').with_value('description')
-      should contain_keystone_config('ldap/project_name_attribute').with_value('ou')
-      should contain_keystone_config('ldap/project_enabled_attribute').with_value('enabled')
-      should contain_keystone_config('ldap/project_domain_id_attribute').with_value('businessCategory')
-      should contain_keystone_config('ldap/project_attribute_ignore').with_value('')
-      should contain_keystone_config('ldap/project_allow_create').with_value('True')
-      should contain_keystone_config('ldap/project_allow_update').with_value('True')
-      should contain_keystone_config('ldap/project_allow_delete').with_value('True')
-      should contain_keystone_config('ldap/project_enabled_emulation').with_value('False')
-      should contain_keystone_config('ldap/project_enabled_emulation_dn').with_value('True')
-      should contain_keystone_config('ldap/project_additional_attribute_mapping').with_value('cn=enabled,ou=openstack,dc=example,dc=com')
+      is_expected.to contain_keystone_config('ldap/project_tree_dn').with_value('ou=projects,ou=openstack,dc=example,dc=com')
+      is_expected.to contain_keystone_config('ldap/project_filter').with_value('')
+      is_expected.to contain_keystone_config('ldap/project_objectclass').with_value('organizationalUnit')
+      is_expected.to contain_keystone_config('ldap/project_id_attribute').with_value('ou')
+      is_expected.to contain_keystone_config('ldap/project_member_attribute').with_value('member')
+      is_expected.to contain_keystone_config('ldap/project_desc_attribute').with_value('description')
+      is_expected.to contain_keystone_config('ldap/project_name_attribute').with_value('ou')
+      is_expected.to contain_keystone_config('ldap/project_enabled_attribute').with_value('enabled')
+      is_expected.to contain_keystone_config('ldap/project_domain_id_attribute').with_value('businessCategory')
+      is_expected.to contain_keystone_config('ldap/project_attribute_ignore').with_value('')
+      is_expected.to contain_keystone_config('ldap/project_allow_create').with_value('True')
+      is_expected.to contain_keystone_config('ldap/project_allow_update').with_value('True')
+      is_expected.to contain_keystone_config('ldap/project_allow_delete').with_value('True')
+      is_expected.to contain_keystone_config('ldap/project_enabled_emulation').with_value('False')
+      is_expected.to contain_keystone_config('ldap/project_enabled_emulation_dn').with_value('True')
+      is_expected.to contain_keystone_config('ldap/project_additional_attribute_mapping').with_value('cn=enabled,ou=openstack,dc=example,dc=com')
 
       # roles
-      should contain_keystone_config('ldap/role_tree_dn').with_value('ou=roles,ou=openstack,dc=example,dc=com')
-      should contain_keystone_config('ldap/role_filter').with_value('')
-      should contain_keystone_config('ldap/role_objectclass').with_value('organizationalRole')
-      should contain_keystone_config('ldap/role_id_attribute').with_value('cn')
-      should contain_keystone_config('ldap/role_name_attribute').with_value('ou')
-      should contain_keystone_config('ldap/role_member_attribute').with_value('roleOccupant')
-      should contain_keystone_config('ldap/role_attribute_ignore').with_value('description')
-      should contain_keystone_config('ldap/role_allow_create').with_value('True')
-      should contain_keystone_config('ldap/role_allow_update').with_value('True')
-      should contain_keystone_config('ldap/role_allow_delete').with_value('True')
-      should contain_keystone_config('ldap/role_additional_attribute_mapping').with_value('')
+      is_expected.to contain_keystone_config('ldap/role_tree_dn').with_value('ou=roles,ou=openstack,dc=example,dc=com')
+      is_expected.to contain_keystone_config('ldap/role_filter').with_value('')
+      is_expected.to contain_keystone_config('ldap/role_objectclass').with_value('organizationalRole')
+      is_expected.to contain_keystone_config('ldap/role_id_attribute').with_value('cn')
+      is_expected.to contain_keystone_config('ldap/role_name_attribute').with_value('ou')
+      is_expected.to contain_keystone_config('ldap/role_member_attribute').with_value('roleOccupant')
+      is_expected.to contain_keystone_config('ldap/role_attribute_ignore').with_value('description')
+      is_expected.to contain_keystone_config('ldap/role_allow_create').with_value('True')
+      is_expected.to contain_keystone_config('ldap/role_allow_update').with_value('True')
+      is_expected.to contain_keystone_config('ldap/role_allow_delete').with_value('True')
+      is_expected.to contain_keystone_config('ldap/role_additional_attribute_mapping').with_value('')
 
       # groups
-      should contain_keystone_config('ldap/group_tree_dn').with_value('ou=groups,ou=openstack,dc=example,dc=com')
-      should contain_keystone_config('ldap/group_filter').with_value('cn=enabled-groups,cn=groups,cn=accounts,dc=example,dc=com')
-      should contain_keystone_config('ldap/group_objectclass').with_value('organizationalRole')
-      should contain_keystone_config('ldap/group_id_attribute').with_value('cn')
-      should contain_keystone_config('ldap/group_member_attribute').with_value('roleOccupant')
-      should contain_keystone_config('ldap/group_desc_attribute').with_value('description')
-      should contain_keystone_config('ldap/group_name_attribute').with_value('cn')
-      should contain_keystone_config('ldap/group_attribute_ignore').with_value('')
-      should contain_keystone_config('ldap/group_allow_create').with_value('False')
-      should contain_keystone_config('ldap/group_allow_update').with_value('False')
-      should contain_keystone_config('ldap/group_allow_delete').with_value('False')
-      should contain_keystone_config('ldap/group_additional_attribute_mapping').with_value('')
+      is_expected.to contain_keystone_config('ldap/group_tree_dn').with_value('ou=groups,ou=openstack,dc=example,dc=com')
+      is_expected.to contain_keystone_config('ldap/group_filter').with_value('cn=enabled-groups,cn=groups,cn=accounts,dc=example,dc=com')
+      is_expected.to contain_keystone_config('ldap/group_objectclass').with_value('organizationalRole')
+      is_expected.to contain_keystone_config('ldap/group_id_attribute').with_value('cn')
+      is_expected.to contain_keystone_config('ldap/group_member_attribute').with_value('roleOccupant')
+      is_expected.to contain_keystone_config('ldap/group_desc_attribute').with_value('description')
+      is_expected.to contain_keystone_config('ldap/group_name_attribute').with_value('cn')
+      is_expected.to contain_keystone_config('ldap/group_attribute_ignore').with_value('')
+      is_expected.to contain_keystone_config('ldap/group_allow_create').with_value('False')
+      is_expected.to contain_keystone_config('ldap/group_allow_update').with_value('False')
+      is_expected.to contain_keystone_config('ldap/group_allow_delete').with_value('False')
+      is_expected.to contain_keystone_config('ldap/group_additional_attribute_mapping').with_value('')
 
       # tls
-      should contain_keystone_config('ldap/use_tls').with_value('False')
-      should contain_keystone_config('ldap/tls_cacertdir').with_value('/etc/ssl/certs/')
-      should contain_keystone_config('ldap/tls_cacertfile').with_value('/etc/ssl/certs/ca-certificates.crt')
-      should contain_keystone_config('ldap/tls_req_cert').with_value('demand')
+      is_expected.to contain_keystone_config('ldap/use_tls').with_value('False')
+      is_expected.to contain_keystone_config('ldap/tls_cacertdir').with_value('/etc/ssl/certs/')
+      is_expected.to contain_keystone_config('ldap/tls_cacertfile').with_value('/etc/ssl/certs/ca-certificates.crt')
+      is_expected.to contain_keystone_config('ldap/tls_req_cert').with_value('demand')
 
       # ldap pooling
-      should contain_keystone_config('ldap/use_pool').with_value('True')
-      should contain_keystone_config('ldap/pool_size').with_value('20')
-      should contain_keystone_config('ldap/pool_retry_max').with_value('2')
-      should contain_keystone_config('ldap/pool_retry_delay').with_value('0.2')
-      should contain_keystone_config('ldap/pool_connection_timeout').with_value('222')
-      should contain_keystone_config('ldap/pool_connection_lifetime').with_value('222')
-      should contain_keystone_config('ldap/use_auth_pool').with_value('True')
-      should contain_keystone_config('ldap/auth_pool_size').with_value('20')
-      should contain_keystone_config('ldap/auth_pool_connection_lifetime').with_value('200')
+      is_expected.to contain_keystone_config('ldap/use_pool').with_value('True')
+      is_expected.to contain_keystone_config('ldap/pool_size').with_value('20')
+      is_expected.to contain_keystone_config('ldap/pool_retry_max').with_value('2')
+      is_expected.to contain_keystone_config('ldap/pool_retry_delay').with_value('0.2')
+      is_expected.to contain_keystone_config('ldap/pool_connection_timeout').with_value('222')
+      is_expected.to contain_keystone_config('ldap/pool_connection_lifetime').with_value('222')
+      is_expected.to contain_keystone_config('ldap/use_auth_pool').with_value('True')
+      is_expected.to contain_keystone_config('ldap/auth_pool_size').with_value('20')
+      is_expected.to contain_keystone_config('ldap/auth_pool_connection_lifetime').with_value('200')
 
       # drivers
-      should contain_keystone_config('identity/driver').with_value('keystone.identity.backends.ldap.Identity')
-      should contain_keystone_config('assignment/driver').with_value('keystone.assignment.backends.ldap.Assignment')
+      is_expected.to contain_keystone_config('identity/driver').with_value('keystone.identity.backends.ldap.Identity')
+      is_expected.to contain_keystone_config('credential/driver').with_value('keystone.credential.backends.ldap.Credential')
+      is_expected.to contain_keystone_config('assignment/driver').with_value('keystone.assignment.backends.ldap.Assignment')
     end
   end
 
@@ -208,22 +210,22 @@ describe 'keystone::ldap' do
       }
     end
     it 'should work with deprecated params' do
-      should contain_keystone_config('ldap/project_tree_dn').with_value('ou=projects,ou=openstack,dc=example,dc=com')
-      should contain_keystone_config('ldap/project_filter').with_value('')
-      should contain_keystone_config('ldap/project_objectclass').with_value('organizationalUnit')
-      should contain_keystone_config('ldap/project_id_attribute').with_value('ou')
-      should contain_keystone_config('ldap/project_member_attribute').with_value('member')
-      should contain_keystone_config('ldap/project_desc_attribute').with_value('description')
-      should contain_keystone_config('ldap/project_name_attribute').with_value('ou')
-      should contain_keystone_config('ldap/project_enabled_attribute').with_value('enabled')
-      should contain_keystone_config('ldap/project_domain_id_attribute').with_value('businessCategory')
-      should contain_keystone_config('ldap/project_attribute_ignore').with_value('')
-      should contain_keystone_config('ldap/project_allow_create').with_value('True')
-      should contain_keystone_config('ldap/project_allow_update').with_value('True')
-      should contain_keystone_config('ldap/project_allow_delete').with_value('True')
-      should contain_keystone_config('ldap/project_enabled_emulation').with_value('False')
-      should contain_keystone_config('ldap/project_enabled_emulation_dn').with_value('True')
-      should contain_keystone_config('ldap/project_additional_attribute_mapping').with_value('cn=enabled,ou=openstack,dc=example,dc=com')
+      is_expected.to contain_keystone_config('ldap/project_tree_dn').with_value('ou=projects,ou=openstack,dc=example,dc=com')
+      is_expected.to contain_keystone_config('ldap/project_filter')
+      is_expected.to contain_keystone_config('ldap/project_objectclass').with_value('organizationalUnit')
+      is_expected.to contain_keystone_config('ldap/project_id_attribute').with_value('ou')
+      is_expected.to contain_keystone_config('ldap/project_member_attribute').with_value('member')
+      is_expected.to contain_keystone_config('ldap/project_desc_attribute').with_value('description')
+      is_expected.to contain_keystone_config('ldap/project_name_attribute').with_value('ou')
+      is_expected.to contain_keystone_config('ldap/project_enabled_attribute').with_value('enabled')
+      is_expected.to contain_keystone_config('ldap/project_domain_id_attribute').with_value('businessCategory')
+      is_expected.to contain_keystone_config('ldap/project_attribute_ignore')
+      is_expected.to contain_keystone_config('ldap/project_allow_create').with_value('True')
+      is_expected.to contain_keystone_config('ldap/project_allow_update').with_value('True')
+      is_expected.to contain_keystone_config('ldap/project_allow_delete').with_value('True')
+      is_expected.to contain_keystone_config('ldap/project_enabled_emulation').with_value('False')
+      is_expected.to contain_keystone_config('ldap/project_enabled_emulation_dn').with_value('True')
+      is_expected.to contain_keystone_config('ldap/project_additional_attribute_mapping').with_value('cn=enabled,ou=openstack,dc=example,dc=com')
     end
   end
 
@@ -234,10 +236,7 @@ describe 'keystone::ldap' do
         :project_tree_dn => 'ou=projects,ou=new-openstack,dc=example,dc=com',
       }
     end
-    it 'should fail with deprecated and new params both set' do
-        expect {
-            should compile
-        }.to raise_error Puppet::Error, /tenant_tree_dn and project_tree_dn are both set. results may be unexpected/
-    end
+
+    it_raises 'a Puppet::Error', /tenant_tree_dn and project_tree_dn are both set. results may be unexpected/
   end
 end
index 7ae935201b354830154f400ca48497e0795a4853..f0ac50d7c5265847b24600c9df7bdc3dce2372e7 100644 (file)
@@ -42,36 +42,36 @@ describe 'keystone::logging' do
 
   shared_examples_for 'logging params set' do
     it 'enables logging params' do
-      should contain_keystone_config('DEFAULT/logging_context_format_string').with_value(
+      is_expected.to contain_keystone_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')
 
-      should contain_keystone_config('DEFAULT/logging_default_format_string').with_value(
+      is_expected.to contain_keystone_config('DEFAULT/logging_default_format_string').with_value(
         '%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s')
 
-      should contain_keystone_config('DEFAULT/logging_debug_format_suffix').with_value(
+      is_expected.to contain_keystone_config('DEFAULT/logging_debug_format_suffix').with_value(
         '%(funcName)s %(pathname)s:%(lineno)d')
 
-      should contain_keystone_config('DEFAULT/logging_exception_prefix').with_value(
+      is_expected.to contain_keystone_config('DEFAULT/logging_exception_prefix').with_value(
        '%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s')
 
-      should contain_keystone_config('DEFAULT/log_config_append').with_value(
+      is_expected.to contain_keystone_config('DEFAULT/log_config_append').with_value(
         '/etc/keystone/logging.conf')
-      should contain_keystone_config('DEFAULT/publish_errors').with_value(
+      is_expected.to contain_keystone_config('DEFAULT/publish_errors').with_value(
         true)
 
-      should contain_keystone_config('DEFAULT/default_log_levels').with_value(
+      is_expected.to contain_keystone_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')
 
-      should contain_keystone_config('DEFAULT/fatal_deprecations').with_value(
+      is_expected.to contain_keystone_config('DEFAULT/fatal_deprecations').with_value(
         true)
 
-      should contain_keystone_config('DEFAULT/instance_format').with_value(
+      is_expected.to contain_keystone_config('DEFAULT/instance_format').with_value(
         '[instance: %(uuid)s] ')
 
-      should contain_keystone_config('DEFAULT/instance_uuid_format').with_value(
+      is_expected.to contain_keystone_config('DEFAULT/instance_uuid_format').with_value(
         '[instance: %(uuid)s] ')
 
-      should contain_keystone_config('DEFAULT/log_date_format').with_value(
+      is_expected.to contain_keystone_config('DEFAULT/log_date_format').with_value(
         '%Y-%m-%d %H:%M:%S')
     end
   end
@@ -84,7 +84,7 @@ describe 'keystone::logging' do
      :default_log_levels, :fatal_deprecations,
      :instance_format, :instance_uuid_format,
      :log_date_format, ].each { |param|
-        it { should contain_keystone_config("DEFAULT/#{param}").with_ensure('absent') }
+        it { is_expected.to contain_keystone_config("DEFAULT/#{param}").with_ensure('absent') }
       }
   end
 
index 81f69da5fbbbe5b61e887b05de7a1d034c5f2a63..56c8f8bc4173736b7ea09e5e52303918110a0690 100644 (file)
@@ -16,7 +16,7 @@ describe 'keystone::policy' do
     end
 
     it 'set up the policies' do
-      should contain_openstacklib__policy__base('context_is_admin').with({
+      is_expected.to contain_openstacklib__policy__base('context_is_admin').with({
         :key   => 'context_is_admin',
         :value => 'foo:bar'
       })
index 1324fb2f673a6875a5cb0ec9ffe0d7ae30e312e1..500413e961ba09b58cae04e30dbcd5e49ce41645 100644 (file)
@@ -6,12 +6,12 @@ describe 'keystone::python' do
     { :osfamily => 'Debian' }
   end
 
-  it { should contain_package('python-keystone').with_ensure("present") }
+  it { is_expected.to contain_package('python-keystone').with_ensure("present") }
 
   describe 'override ensure' do
     let(:params) { { :ensure => "latest" } }
 
-    it { should contain_package('python-keystone').with_ensure("latest") }
+    it { is_expected.to contain_package('python-keystone').with_ensure("latest") }
   end
 
 end
index ba7d53296a2ac115a11ad0bd48031d4e3fe7abad..bbd6d953b8316995b7514cdf445521da5b808f1d 100644 (file)
@@ -11,17 +11,17 @@ describe 'keystone::roles::admin' do
       }
     end
 
-    it { should contain_keystone_tenant('services').with(
+    it { is_expected.to contain_keystone_tenant('services').with(
       :ensure      => 'present',
       :enabled     => true,
       :description => 'Tenant for the openstack services'
     )}
-    it { should contain_keystone_tenant('openstack').with(
+    it { is_expected.to contain_keystone_tenant('openstack').with(
       :ensure      => 'present',
       :enabled     => true,
       :description => 'admin tenant'
     )}
-    it { should contain_keystone_user('admin').with(
+    it { is_expected.to contain_keystone_user('admin').with(
       :ensure                 => 'present',
       :enabled                => true,
       :tenant                 => 'openstack',
@@ -29,8 +29,8 @@ describe 'keystone::roles::admin' do
       :password               => 'ChangeMe',
       :ignore_default_tenant  => 'false'
     )}
-    it { should contain_keystone_role('admin').with_ensure('present') }
-    it { should contain_keystone_user_role('admin@openstack').with(
+    it { is_expected.to contain_keystone_role('admin').with_ensure('present') }
+    it { is_expected.to contain_keystone_user_role('admin@openstack').with(
       :roles  => ['admin'],
       :ensure => 'present'
     )}
@@ -53,17 +53,17 @@ describe 'keystone::roles::admin' do
       }
     end
 
-    it { should contain_keystone_tenant('foobar').with(
+    it { is_expected.to contain_keystone_tenant('foobar').with(
       :ensure  => 'present',
       :enabled => true,
       :description => 'foobar description'
     )}
-    it { should contain_keystone_tenant('admin').with(
+    it { is_expected.to contain_keystone_tenant('admin').with(
       :ensure      => 'present',
       :enabled     => true,
       :description => 'admin something else'
     )}
-    it { should contain_keystone_user('admin').with(
+    it { is_expected.to contain_keystone_user('admin').with(
       :ensure                 => 'present',
       :enabled                => true,
       :tenant                 => 'admin',
@@ -71,7 +71,7 @@ describe 'keystone::roles::admin' do
       :password               => 'foo',
       :ignore_default_tenant  => 'true'
     )}
-    it { should contain_keystone_user_role('admin@admin').with(
+    it { is_expected.to contain_keystone_user_role('admin@admin').with(
       :roles  => ['admin', 'heat_stack_owner'],
       :ensure => 'present'
     )}
@@ -86,8 +86,8 @@ describe 'keystone::roles::admin' do
         }
       end
 
-      it { should_not contain_keystone_user('keystone') }
-      it { should contain_keystone_user_role('keystone@openstack') }
+      it { is_expected.to_not contain_keystone_user('keystone') }
+      it { is_expected.to contain_keystone_user_role('keystone@openstack') }
     end
   end
 
@@ -100,8 +100,8 @@ describe 'keystone::roles::admin' do
         }
       end
 
-      it { should_not contain_keystone_user('keystone') }
-      it { should_not contain_keystone_user_role('keystone@openstack') }
+      it { is_expected.to_not contain_keystone_user('keystone') }
+      it { is_expected.to_not contain_keystone_user_role('keystone@openstack') }
     end
   end
 
index 29d90b0d5ec11e0b6b2b0e7a363d9d485b21d5aa..3aa302d631e1ce91dea73cb8c4862787fa0eb7ad 100644 (file)
@@ -3,13 +3,13 @@ require 'spec_helper'
 describe 'keystone::service' do
 
   describe "with default parameters" do
-    it { should contain_service('keystone').with(
-      :ensure     => 'running',
+    it { is_expected.to contain_service('keystone').with(
+      :ensure     => nil,
       :enable     => true,
       :hasstatus  => true,
       :hasrestart => true
     ) }
-    it { should_not contain_exec('validate_keystone_connection') }
+    it { is_expected.to_not contain_exec('validate_keystone_connection') }
   end
 
   describe "with validation on" do
@@ -20,12 +20,12 @@ describe 'keystone::service' do
       }
     end
 
-    it { should contain_service('keystone').with(
-      :ensure     => 'running',
+    it { is_expected.to contain_service('keystone').with(
+      :ensure     => nil,
       :enable     => true,
       :hasstatus  => true,
       :hasrestart => true
     ) }
-    it { should contain_exec('validate_keystone_connection') }
+    it { is_expected.to contain_exec('validate_keystone_connection') }
   end
 end
index ef6358550d595a8ad9dc7cb9414d9c41b55887a2..89c4fc55e51580dc276da1f256c384e41c733a72 100644 (file)
@@ -14,25 +14,27 @@ describe 'keystone' do
     global_facts.merge({
       :osfamily               => 'Debian',
       :operatingsystem        => 'Debian',
-      :operatingsystemrelease => '7.0'
+      :operatingsystemrelease => '7.0',
+      :processorcount         => '1'
     })
   end
 
   default_params = {
       'admin_token'           => 'service_token',
       'package_ensure'        => 'present',
+      'client_package_ensure' => 'present',
       'public_bind_host'      => '0.0.0.0',
       'admin_bind_host'       => '0.0.0.0',
       'public_port'           => '5000',
       'admin_port'            => '35357',
       'admin_token'           => 'service_token',
-      'compute_port'          => '8774',
       'verbose'               => false,
       'debug'                 => false,
       'catalog_type'          => 'sql',
       'catalog_driver'        => false,
       'token_provider'        => 'keystone.token.providers.uuid.Provider',
       'token_driver'          => 'keystone.token.persistence.backends.sql.Token',
+      'revoke_driver'         => 'keystone.contrib.revoke.backends.sql.Revoke',
       'cache_dir'             => '/var/cache/keystone',
       'enable_ssl'            => false,
       'ssl_certfile'          => '/etc/keystone/ssl/certs/keystone.pem',
@@ -41,6 +43,7 @@ describe 'keystone' do
       'ssl_ca_key'            => '/etc/keystone/ssl/private/cakey.pem',
       'ssl_cert_subject'      => '/C=US/ST=Unset/L=Unset/O=Unset/CN=localhost',
       'enabled'               => true,
+      'manage_service'        => true,
       'database_connection'   => 'sqlite:////var/lib/keystone/keystone.db',
       'database_idle_timeout' => '200',
       'enable_pki_setup'      => true,
@@ -51,21 +54,25 @@ describe 'keystone' do
       'rabbit_host'           => 'localhost',
       'rabbit_password'       => 'guest',
       'rabbit_userid'         => 'guest',
+      'admin_workers'         => 20,
+      'public_workers'        => 20,
+      'sync_db'               => true,
     }
 
   override_params = {
       'package_ensure'        => 'latest',
+      'client_package_ensure' => 'latest',
       'public_bind_host'      => '0.0.0.0',
       'admin_bind_host'       => '0.0.0.0',
       'public_port'           => '5001',
       'admin_port'            => '35358',
       'admin_token'           => 'service_token_override',
-      'compute_port'          => '8778',
       'verbose'               => true,
       'debug'                 => true,
       'catalog_type'          => 'template',
       'token_provider'        => 'keystone.token.providers.uuid.Provider',
       'token_driver'          => 'keystone.token.backends.kvs.Token',
+      'revoke_driver'         => 'keystone.contrib.revoke.backends.kvs.Revoke',
       'public_endpoint'       => 'https://localhost:5000/v2.0/',
       'admin_endpoint'        => 'https://localhost:35357/v2.0/',
       'enable_ssl'            => true,
@@ -75,6 +82,7 @@ describe 'keystone' do
       'ssl_ca_key'            => '/etc/keystone/ssl/private/cakey.pem',
       'ssl_cert_subject'      => '/C=US/ST=Unset/L=Unset/O=Unset/CN=localhost',
       'enabled'               => false,
+      'manage_service'        => true,
       'database_connection'   => 'mysql://a:b@c/d',
       'database_idle_timeout' => '300',
       'enable_pki_setup'      => true,
@@ -90,19 +98,24 @@ describe 'keystone' do
   httpd_params = {'service_name' => 'httpd'}.merge(default_params)
 
   shared_examples_for 'core keystone examples' do |param_hash|
-    it { should contain_class('keystone::params') }
+    it { is_expected.to contain_class('keystone::params') }
 
-    it { should contain_package('keystone').with(
+    it { is_expected.to contain_package('keystone').with(
       'ensure' => param_hash['package_ensure'],
       'tag'    => 'openstack'
     ) }
 
-    it { should contain_group('keystone').with(
+    it { is_expected.to contain_package('python-openstackclient').with(
+      'ensure' => param_hash['client_package_ensure'],
+      'tag'    => 'openstack'
+    ) }
+
+    it { is_expected.to contain_group('keystone').with(
       'ensure' => 'present',
       'system' => true
     ) }
 
-    it { should contain_user('keystone').with(
+    it { is_expected.to contain_user('keystone').with(
       'ensure' => 'present',
       'gid'    => 'keystone',
       'system' => true
@@ -110,7 +123,7 @@ describe 'keystone' do
 
     it 'should contain the expected directories' do
       ['/etc/keystone', '/var/log/keystone', '/var/lib/keystone'].each do |d|
-        should contain_file(d).with(
+        is_expected.to contain_file(d).with(
           'ensure'     => 'directory',
           'owner'      => 'keystone',
           'group'      => 'keystone',
@@ -120,9 +133,9 @@ describe 'keystone' do
       end
     end
 
-    it 'should only synchronize the db if $enabled is true' do
-      if param_hash['enabled']
-        should contain_exec('keystone-manage db_sync').with(
+    it 'should synchronize the db if $sync_db is true' do
+      if param_hash['sync_db']
+        is_expected.to contain_exec('keystone-manage db_sync').with(
           :user        => 'keystone',
           :refreshonly => true,
           :subscribe   => ['Package[keystone]', 'Keystone_config[database/connection]'],
@@ -137,46 +150,66 @@ describe 'keystone' do
        'admin_bind_host',
        'public_port',
        'admin_port',
-       'compute_port',
        'verbose',
        'debug'
       ].each do |config|
-        should contain_keystone_config("DEFAULT/#{config}").with_value(param_hash[config])
+        is_expected.to contain_keystone_config("DEFAULT/#{config}").with_value(param_hash[config])
       end
     end
 
     it 'should contain correct admin_token config' do
-      should contain_keystone_config('DEFAULT/admin_token').with_value(param_hash['admin_token']).with_secret(true)
+      is_expected.to contain_keystone_config('DEFAULT/admin_token').with_value(param_hash['admin_token']).with_secret(true)
     end
 
     it 'should contain correct mysql config' do
-      should contain_keystone_config('database/idle_timeout').with_value(param_hash['database_idle_timeout'])
-      should contain_keystone_config('database/connection').with_value(param_hash['database_connection']).with_secret(true)
+      is_expected.to contain_keystone_config('database/idle_timeout').with_value(param_hash['database_idle_timeout'])
+      is_expected.to contain_keystone_config('database/connection').with_value(param_hash['database_connection']).with_secret(true)
     end
 
-    it { should contain_keystone_config('token/provider').with_value(
+    it { is_expected.to contain_keystone_config('token/provider').with_value(
       param_hash['token_provider']
     ) }
 
     it 'should contain correct token driver' do
-      should contain_keystone_config('token/driver').with_value(param_hash['token_driver'])
+      is_expected.to contain_keystone_config('token/driver').with_value(param_hash['token_driver'])
+    end
+
+    it 'should contain correct revoke driver' do
+      should contain_keystone_config('revoke/driver').with_value(param_hash['revoke_driver'])
     end
 
     it 'should ensure proper setting of admin_endpoint and public_endpoint' do
       if param_hash['admin_endpoint']
-        should contain_keystone_config('DEFAULT/admin_endpoint').with_value(param_hash['admin_endpoint'])
+        is_expected.to contain_keystone_config('DEFAULT/admin_endpoint').with_value(param_hash['admin_endpoint'])
       else
-        should contain_keystone_config('DEFAULT/admin_endpoint').with_ensure('absent')
+        is_expected.to contain_keystone_config('DEFAULT/admin_endpoint').with_ensure('absent')
       end
       if param_hash['public_endpoint']
-        should contain_keystone_config('DEFAULT/public_endpoint').with_value(param_hash['public_endpoint'])
+        is_expected.to contain_keystone_config('DEFAULT/public_endpoint').with_value(param_hash['public_endpoint'])
       else
-        should contain_keystone_config('DEFAULT/public_endpoint').with_ensure('absent')
+        is_expected.to contain_keystone_config('DEFAULT/public_endpoint').with_ensure('absent')
       end
     end
 
     it 'should contain correct rabbit_password' do
-      should contain_keystone_config('DEFAULT/rabbit_password').with_value(param_hash['rabbit_password']).with_secret(true)
+      is_expected.to contain_keystone_config('DEFAULT/rabbit_password').with_value(param_hash['rabbit_password']).with_secret(true)
+    end
+
+    it 'should remove max_token_size param by default' do
+      is_expected.to contain_keystone_config('DEFAULT/max_token_size').with_ensure('absent')
+    end
+
+    it 'should ensure proper setting of admin_workers and public_workers' do
+      if param_hash['admin_workers']
+        is_expected.to contain_keystone_config('DEFAULT/admin_workers').with_value(param_hash['admin_workers'])
+      else
+        is_expected.to contain_keystone_config('DEFAULT/admin_workers').with_value('2')
+      end
+      if param_hash['public_workers']
+        is_expected.to contain_keystone_config('DEFAULT/public_workers').with_value(param_hash['public_workers'])
+      else
+        is_expected.to contain_keystone_config('DEFAULT/public_workers').with_value('2')
+      end
     end
   end
 
@@ -189,8 +222,8 @@ describe 'keystone' do
 
       it_configures 'core keystone examples', param_hash
 
-      it { should contain_service('keystone').with(
-        'ensure'     => param_hash['enabled'] ? 'running' : 'stopped',
+      it { is_expected.to contain_service('keystone').with(
+        'ensure'     => (param_hash['manage_service'] && param_hash['enabled']) ? 'running' : 'stopped',
         'enable'     => param_hash['enabled'],
         'hasstatus'  => true,
         'hasrestart' => true
@@ -199,7 +232,7 @@ describe 'keystone' do
     end
   end
 
-  describe "when using default class parameters for httpd" do
+  shared_examples_for "when using default class parameters for httpd" do
     let :params do
       httpd_params
     end
@@ -212,28 +245,37 @@ describe 'keystone' do
 
     it do
       expect {
-        should contain_service('keystone')
-      }.to raise_error(RSpec::Expectations::ExpectationNotMetError, /expected that the catalogue would contain Service\[keystone\]/)
+        should 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(
+      'ensure'          => 'stopped',
+      'service_name'    => platform_parameters[:service_name],
+      'enable'          => false,
+      'validate'        => false
+    )}
   end
 
-  describe 'with deprecated sql_connection parameter' do
-    let :params do
-      { :admin_token    => 'service_token',
-        :sql_connection => 'mysql://a:b@c/d' }
-    end
+  describe 'when using invalid service name for keystone' do
+    let (:params) { {'service_name' => 'foo'}.merge(default_params) }
 
-    it { should contain_keystone_config('database/connection').with_value(params[:sql_connection]) }
+    it_raises 'a Puppet::Error', /Invalid service_name/
   end
 
-  describe 'with deprecated idle_timeout parameter' do
+  describe 'with disabled service managing' do
     let :params do
-      { :admin_token  => 'service_token',
-        :idle_timeout => 365 }
+      { :admin_token    => 'service_token',
+        :manage_service => false,
+        :enabled        => false }
     end
 
-    it { should contain_keystone_config('database/idle_timeout').with_value(params[:idle_timeout]) }
+    it { is_expected.to contain_service('keystone').with(
+      'ensure'     => nil,
+      'enable'     => false,
+      'hasstatus'  => true,
+      'hasrestart' => true
+    ) }
   end
 
   describe 'when configuring signing token provider' do
@@ -245,23 +287,23 @@ describe 'keystone' do
           'token_provider' => 'keystone.token.providers.uuid.Provider'
         }
       end
-      it { should contain_exec('keystone-manage pki_setup').with(
+      it { is_expected.to contain_exec('keystone-manage pki_setup').with(
         :creates => '/etc/keystone/ssl/private/signing_key.pem'
       ) }
-      it { should contain_file('/var/cache/keystone').with_ensure('directory') }
+      it { is_expected.to contain_file('/var/cache/keystone').with_ensure('directory') }
 
       describe 'when overriding the cache dir' do
         before do
           params.merge!(:cache_dir => '/var/lib/cache/keystone')
         end
-        it { should contain_file('/var/lib/cache/keystone') }
+        it { is_expected.to contain_file('/var/lib/cache/keystone') }
       end
 
       describe 'when disable pki_setup' do
         before do
           params.merge!(:enable_pki_setup => false)
         end
-        it { should_not contain_exec('keystone-manage pki_setup') }
+        it { is_expected.to_not contain_exec('keystone-manage pki_setup') }
       end
     end
 
@@ -272,23 +314,23 @@ describe 'keystone' do
           'token_provider' => 'keystone.token.providers.pki.Provider'
         }
       end
-      it { should contain_exec('keystone-manage pki_setup').with(
+      it { is_expected.to contain_exec('keystone-manage pki_setup').with(
         :creates => '/etc/keystone/ssl/private/signing_key.pem'
       ) }
-      it { should contain_file('/var/cache/keystone').with_ensure('directory') }
+      it { is_expected.to contain_file('/var/cache/keystone').with_ensure('directory') }
 
       describe 'when overriding the cache dir' do
         before do
           params.merge!(:cache_dir => '/var/lib/cache/keystone')
         end
-        it { should contain_file('/var/lib/cache/keystone') }
+        it { is_expected.to contain_file('/var/lib/cache/keystone') }
       end
 
       describe 'when disable pki_setup' do
         before do
           params.merge!(:enable_pki_setup => false)
         end
-        it { should_not contain_exec('keystone-manage pki_setup') }
+        it { is_expected.to_not contain_exec('keystone-manage pki_setup') }
       end
     end
 
@@ -307,30 +349,30 @@ describe 'keystone' do
         }
       end
 
-      it { should_not contain_exec('keystone-manage pki_setup') }
+      it { is_expected.to_not contain_exec('keystone-manage pki_setup') }
 
       it 'should contain correct PKI certfile config' do
-        should contain_keystone_config('signing/certfile').with_value('signing_certfile')
+        is_expected.to contain_keystone_config('signing/certfile').with_value('signing_certfile')
       end
 
       it 'should contain correct PKI keyfile config' do
-        should contain_keystone_config('signing/keyfile').with_value('signing_keyfile')
+        is_expected.to contain_keystone_config('signing/keyfile').with_value('signing_keyfile')
       end
 
       it 'should contain correct PKI ca_certs config' do
-        should contain_keystone_config('signing/ca_certs').with_value('signing_ca_certs')
+        is_expected.to contain_keystone_config('signing/ca_certs').with_value('signing_ca_certs')
       end
 
       it 'should contain correct PKI ca_key config' do
-        should contain_keystone_config('signing/ca_key').with_value('signing_ca_key')
+        is_expected.to contain_keystone_config('signing/ca_key').with_value('signing_ca_key')
       end
 
       it 'should contain correct PKI cert_subject config' do
-        should contain_keystone_config('signing/cert_subject').with_value('signing_cert_subject')
+        is_expected.to contain_keystone_config('signing/cert_subject').with_value('signing_cert_subject')
       end
 
       it 'should contain correct PKI key_size config' do
-        should contain_keystone_config('signing/key_size').with_value('2048')
+        is_expected.to contain_keystone_config('signing/key_size').with_value('2048')
       end
     end
 
@@ -349,30 +391,30 @@ describe 'keystone' do
         }
       end
 
-      it { should_not contain_exec('keystone-manage pki_setup') }
+      it { is_expected.to_not contain_exec('keystone-manage pki_setup') }
 
       it 'should contain correct PKI certfile config' do
-        should contain_keystone_config('signing/certfile').with_value('signing_certfile')
+        is_expected.to contain_keystone_config('signing/certfile').with_value('signing_certfile')
       end
 
       it 'should contain correct PKI keyfile config' do
-        should contain_keystone_config('signing/keyfile').with_value('signing_keyfile')
+        is_expected.to contain_keystone_config('signing/keyfile').with_value('signing_keyfile')
       end
 
       it 'should contain correct PKI ca_certs config' do
-        should contain_keystone_config('signing/ca_certs').with_value('signing_ca_certs')
+        is_expected.to contain_keystone_config('signing/ca_certs').with_value('signing_ca_certs')
       end
 
       it 'should contain correct PKI ca_key config' do
-        should contain_keystone_config('signing/ca_key').with_value('signing_ca_key')
+        is_expected.to contain_keystone_config('signing/ca_key').with_value('signing_ca_key')
       end
 
       it 'should contain correct PKI cert_subject config' do
-        should contain_keystone_config('signing/cert_subject').with_value('signing_cert_subject')
+        is_expected.to contain_keystone_config('signing/cert_subject').with_value('signing_cert_subject')
       end
 
       it 'should contain correct PKI key_size config' do
-        should contain_keystone_config('signing/key_size').with_value('2048')
+        is_expected.to contain_keystone_config('signing/key_size').with_value('2048')
       end
     end
 
@@ -391,99 +433,8 @@ describe 'keystone' do
           :catalog_driver => 'keystone.catalog.backends.alien.AlienCatalog' }
       end
 
-      it { should contain_keystone_config('catalog/driver').with_value(params[:catalog_driver]) }
-    end
-
-    describe 'when configuring deprecated token_format as UUID with enable_pki_setup' do
-      let :params do
-        {
-          'admin_token'    => 'service_token',
-          'token_format'   => 'UUID'
-        }
-      end
-      it { should contain_exec('keystone-manage pki_setup').with(
-        :creates => '/etc/keystone/ssl/private/signing_key.pem'
-      ) }
-      it { should contain_file('/var/cache/keystone').with_ensure('directory') }
-      describe 'when overriding the cache dir' do
-        let :params do
-          {
-            'admin_token'    => 'service_token',
-            'token_provider' => 'keystone.token.providers.pki.Provider',
-            'cache_dir'      => '/var/lib/cache/keystone'
-          }
-        end
-        it { should contain_file('/var/lib/cache/keystone') }
-      end
-    end
-
-    describe 'when configuring deprecated token_format as UUID without enable_pki_setup' do
-      let :params do
-        {
-          'admin_token'      => 'service_token',
-          'token_format'     => 'UUID',
-          'enable_pki_setup' => false
-        }
-      end
-      it { should_not contain_exec('keystone-manage pki_setup') }
-      it { should contain_file('/var/cache/keystone').with_ensure('directory') }
-      describe 'when overriding the cache dir' do
-        let :params do
-          {
-            'admin_token'    => 'service_token',
-            'token_provider' => 'keystone.token.providers.uuid.Provider',
-            'cache_dir'      => '/var/lib/cache/keystone'
-          }
-        end
-        it { should contain_file('/var/lib/cache/keystone') }
-      end
-    end
-
-    describe 'when configuring deprecated token_format as PKI with enable_pki_setup' do
-      let :params do
-        {
-          'admin_token'       => 'service_token',
-          'token_format'      => 'PKI',
-        }
-      end
-      it { should contain_exec('keystone-manage pki_setup').with(
-        :creates => '/etc/keystone/ssl/private/signing_key.pem'
-      ) }
-      it { should contain_file('/var/cache/keystone').with_ensure('directory') }
-      describe 'when overriding the cache dir' do
-        let :params do
-          {
-            'admin_token'    => 'service_token',
-            'token_provider' => 'keystone.token.providers.pki.Provider',
-            'cache_dir'      => '/var/lib/cache/keystone'
-          }
-        end
-        it { should contain_file('/var/lib/cache/keystone') }
-      end
+      it { is_expected.to contain_keystone_config('catalog/driver').with_value(params[:catalog_driver]) }
     end
-
-    describe 'when configuring deprecated token_format as PKI without enable_pki_setup' do
-      let :params do
-        {
-          'admin_token'       => 'service_token',
-          'token_format'      => 'PKI',
-          'enable_pki_setup'  => false
-        }
-      end
-      it { should_not contain_exec('keystone-manage pki_setup') }
-      it { should contain_file('/var/cache/keystone').with_ensure('directory') }
-      describe 'when overriding the cache dir' do
-        let :params do
-          {
-            'admin_token'    => 'service_token',
-            'token_provider' => 'keystone.token.providers.pki.Provider',
-            'cache_dir'      => '/var/lib/cache/keystone'
-          }
-        end
-        it { should contain_file('/var/lib/cache/keystone') }
-      end
-    end
-
   end
 
   describe 'when configuring token expiration' do
@@ -494,7 +445,7 @@ describe 'keystone' do
       }
     end
 
-    it { should contain_keystone_config("token/expiration").with_value('42') }
+    it { is_expected.to contain_keystone_config("token/expiration").with_value('42') }
   end
 
   describe 'when not configuring token expiration' do
@@ -504,7 +455,18 @@ describe 'keystone' do
       }
     end
 
-    it { should contain_keystone_config("token/expiration").with_value('3600') }
+    it { is_expected.to contain_keystone_config("token/expiration").with_value('3600') }
+  end
+
+  describe 'when sync_db is set to false' do
+    let :params do
+      {
+        'admin_token' => 'service_token',
+        'sync_db'     => false,
+      }
+    end
+
+    it { is_expected.not_to contain_exec('keystone-manage db_sync') }
   end
 
   describe 'configure memcache servers if set' do
@@ -518,12 +480,12 @@ describe 'keystone' do
       }
     end
 
-    it { should contain_keystone_config("memcache/servers").with_value('SERVER1:11211,SERVER2:11211') }
-    it { should contain_keystone_config('cache/enabled').with_value(true) }
-    it { should contain_keystone_config('token/caching').with_value(true) }
-    it { should contain_keystone_config('cache/backend').with_value('dogpile.cache.memcached') }
-    it { should contain_keystone_config('cache/backend_argument').with_value('url:SERVER1:12211') }
-    it { should contain_package('python-memcache').with(
+    it { is_expected.to contain_keystone_config("memcache/servers").with_value('SERVER1:11211,SERVER2:11211') }
+    it { is_expected.to contain_keystone_config('cache/enabled').with_value(true) }
+    it { is_expected.to contain_keystone_config('token/caching').with_value(true) }
+    it { is_expected.to contain_keystone_config('cache/backend').with_value('dogpile.cache.memcached') }
+    it { is_expected.to contain_keystone_config('cache/backend_argument').with_value('url:SERVER1:12211') }
+    it { is_expected.to contain_package('python-memcache').with(
       :name   => 'python-memcache',
       :ensure => 'present'
     ) }
@@ -534,12 +496,12 @@ describe 'keystone' do
       default_params
     end
 
-    it { should contain_keystone_config("cache/enabled").with_ensure('absent') }
-    it { should contain_keystone_config("token/caching").with_ensure('absent') }
-    it { should contain_keystone_config("cache/backend").with_ensure('absent') }
-    it { should contain_keystone_config("cache/backend_argument").with_ensure('absent') }
-    it { should contain_keystone_config("cache/debug_cache_backend").with_ensure('absent') }
-    it { should contain_keystone_config("memcache/servers").with_ensure('absent') }
+    it { is_expected.to contain_keystone_config("cache/enabled").with_ensure('absent') }
+    it { is_expected.to contain_keystone_config("token/caching").with_ensure('absent') }
+    it { is_expected.to contain_keystone_config("cache/backend").with_ensure('absent') }
+    it { is_expected.to contain_keystone_config("cache/backend_argument").with_ensure('absent') }
+    it { is_expected.to contain_keystone_config("cache/debug_cache_backend").with_ensure('absent') }
+    it { is_expected.to contain_keystone_config("memcache/servers").with_ensure('absent') }
   end
 
   describe 'raise error if memcache_servers is not an array' do
@@ -550,7 +512,7 @@ describe 'keystone' do
       }
     end
 
-    it { expect { should contain_class('keystone::params') }.to \
+    it { expect { is_expected.to contain_class('keystone::params') }.to \
       raise_error(Puppet::Error, /is not an Array/) }
   end
 
@@ -559,8 +521,8 @@ describe 'keystone' do
       default_params
     end
 
-    it { should contain_keystone_config('DEFAULT/use_syslog').with_value(false) }
-    it { should_not contain_keystone_config('DEFAULT/syslog_log_facility') }
+    it { is_expected.to contain_keystone_config('DEFAULT/use_syslog').with_value(false) }
+    it { is_expected.to_not contain_keystone_config('DEFAULT/syslog_log_facility') }
   end
 
   describe 'with syslog enabled' do
@@ -570,8 +532,8 @@ describe 'keystone' do
       })
     end
 
-    it { should contain_keystone_config('DEFAULT/use_syslog').with_value(true) }
-    it { should contain_keystone_config('DEFAULT/syslog_log_facility').with_value('LOG_USER') }
+    it { is_expected.to contain_keystone_config('DEFAULT/use_syslog').with_value(true) }
+    it { is_expected.to contain_keystone_config('DEFAULT/syslog_log_facility').with_value('LOG_USER') }
   end
 
   describe 'with syslog enabled and custom settings' do
@@ -582,15 +544,15 @@ describe 'keystone' do
      })
     end
 
-    it { should contain_keystone_config('DEFAULT/use_syslog').with_value(true) }
-    it { should contain_keystone_config('DEFAULT/syslog_log_facility').with_value('LOG_LOCAL0') }
+    it { is_expected.to contain_keystone_config('DEFAULT/use_syslog').with_value(true) }
+    it { is_expected.to contain_keystone_config('DEFAULT/syslog_log_facility').with_value('LOG_LOCAL0') }
   end
 
   describe 'with log_file disabled by default' do
     let :params do
       default_params
     end
-    it { should contain_keystone_config('DEFAULT/log_file').with_ensure('absent') }
+    it { is_expected.to contain_keystone_config('DEFAULT/log_file').with_ensure('absent') }
   end
 
   describe 'with log_file and log_dir enabled' do
@@ -600,8 +562,8 @@ describe 'keystone' do
         :log_dir    => '/var/lib/keystone'
      })
     end
-    it { should contain_keystone_config('DEFAULT/log_file').with_value('keystone.log') }
-    it { should contain_keystone_config('DEFAULT/log_dir').with_value('/var/lib/keystone') }
+    it { is_expected.to contain_keystone_config('DEFAULT/log_file').with_value('keystone.log') }
+    it { is_expected.to contain_keystone_config('DEFAULT/log_dir').with_value('/var/lib/keystone') }
   end
 
     describe 'with log_file and log_dir disabled' do
@@ -611,18 +573,8 @@ describe 'keystone' do
         :log_dir    => false
      })
     end
-    it { should contain_keystone_config('DEFAULT/log_file').with_ensure('absent') }
-    it { should contain_keystone_config('DEFAULT/log_dir').with_ensure('absent') }
-  end
-
-  describe 'when configuring api binding with deprecated parameter' do
-    let :params do
-      default_params.merge({
-        :bind_host => '10.0.0.2',
-      })
-    end
-    it { should contain_keystone_config('DEFAULT/public_bind_host').with_value('10.0.0.2') }
-    it { should contain_keystone_config('DEFAULT/admin_bind_host').with_value('10.0.0.2') }
+    it { is_expected.to contain_keystone_config('DEFAULT/log_file').with_ensure('absent') }
+    it { is_expected.to contain_keystone_config('DEFAULT/log_dir').with_ensure('absent') }
   end
 
   describe 'when enabling SSL' do
@@ -634,14 +586,14 @@ describe 'keystone' do
         'admin_endpoint'   => 'https://localhost:35357/v2.0/',
       }
     end
-    it {should contain_keystone_config('ssl/enable').with_value(true)}
-    it {should contain_keystone_config('ssl/certfile').with_value('/etc/keystone/ssl/certs/keystone.pem')}
-    it {should contain_keystone_config('ssl/keyfile').with_value('/etc/keystone/ssl/private/keystonekey.pem')}
-    it {should contain_keystone_config('ssl/ca_certs').with_value('/etc/keystone/ssl/certs/ca.pem')}
-    it {should contain_keystone_config('ssl/ca_key').with_value('/etc/keystone/ssl/private/cakey.pem')}
-    it {should contain_keystone_config('ssl/cert_subject').with_value('/C=US/ST=Unset/L=Unset/O=Unset/CN=localhost')}
-    it {should contain_keystone_config('DEFAULT/public_endpoint').with_value('https://localhost:5000/v2.0/')}
-    it {should contain_keystone_config('DEFAULT/admin_endpoint').with_value('https://localhost:35357/v2.0/')}
+    it {is_expected.to contain_keystone_config('ssl/enable').with_value(true)}
+    it {is_expected.to contain_keystone_config('ssl/certfile').with_value('/etc/keystone/ssl/certs/keystone.pem')}
+    it {is_expected.to contain_keystone_config('ssl/keyfile').with_value('/etc/keystone/ssl/private/keystonekey.pem')}
+    it {is_expected.to contain_keystone_config('ssl/ca_certs').with_value('/etc/keystone/ssl/certs/ca.pem')}
+    it {is_expected.to contain_keystone_config('ssl/ca_key').with_value('/etc/keystone/ssl/private/cakey.pem')}
+    it {is_expected.to contain_keystone_config('ssl/cert_subject').with_value('/C=US/ST=Unset/L=Unset/O=Unset/CN=localhost')}
+    it {is_expected.to contain_keystone_config('DEFAULT/public_endpoint').with_value('https://localhost:5000/v2.0/')}
+    it {is_expected.to contain_keystone_config('DEFAULT/admin_endpoint').with_value('https://localhost:35357/v2.0/')}
   end
   describe 'when disabling SSL' do
     let :params do
@@ -650,18 +602,19 @@ describe 'keystone' do
         'enable_ssl'  => false,
       }
     end
-    it {should contain_keystone_config('ssl/enable').with_value(false)}
-    it {should contain_keystone_config('DEFAULT/public_endpoint').with_ensure('absent')}
-    it {should contain_keystone_config('DEFAULT/admin_endpoint').with_ensure('absent')}
+    it {is_expected.to contain_keystone_config('ssl/enable').with_value(false)}
+    it {is_expected.to contain_keystone_config('DEFAULT/public_endpoint').with_ensure('absent')}
+    it {is_expected.to contain_keystone_config('DEFAULT/admin_endpoint').with_ensure('absent')}
   end
   describe 'not setting notification settings by default' do
     let :params do
       default_params
     end
 
-    it { should contain_keystone_config('DEFAULT/notification_driver').with_value(nil) }
-    it { should contain_keystone_config('DEFAULT/notification_topics').with_vaule(nil) }
-    it { should contain_keystone_config('DEFAULT/control_exchange').with_vaule(nil) }
+    it { is_expected.to contain_keystone_config('DEFAULT/notification_driver').with_value(nil) }
+    it { is_expected.to contain_keystone_config('DEFAULT/notification_topics').with_value(nil) }
+    it { is_expected.to contain_keystone_config('DEFAULT/notification_format').with_value(nil) }
+    it { is_expected.to contain_keystone_config('DEFAULT/control_exchange').with_value(nil) }
   end
 
   describe 'with RabbitMQ communication SSLed' do
@@ -676,11 +629,11 @@ describe 'keystone' do
     end
 
     it do
-      should contain_keystone_config('DEFAULT/rabbit_use_ssl').with_value('true')
-      should contain_keystone_config('DEFAULT/kombu_ssl_ca_certs').with_value('/path/to/ssl/ca/certs')
-      should contain_keystone_config('DEFAULT/kombu_ssl_certfile').with_value('/path/to/ssl/cert/file')
-      should contain_keystone_config('DEFAULT/kombu_ssl_keyfile').with_value('/path/to/ssl/keyfile')
-      should contain_keystone_config('DEFAULT/kombu_ssl_version').with_value('TLSv1')
+      is_expected.to contain_keystone_config('DEFAULT/rabbit_use_ssl').with_value('true')
+      is_expected.to contain_keystone_config('DEFAULT/kombu_ssl_ca_certs').with_value('/path/to/ssl/ca/certs')
+      is_expected.to contain_keystone_config('DEFAULT/kombu_ssl_certfile').with_value('/path/to/ssl/cert/file')
+      is_expected.to contain_keystone_config('DEFAULT/kombu_ssl_keyfile').with_value('/path/to/ssl/keyfile')
+      is_expected.to contain_keystone_config('DEFAULT/kombu_ssl_version').with_value('TLSv1')
     end
   end
 
@@ -696,12 +649,20 @@ describe 'keystone' do
     end
 
     it do
-      should contain_keystone_config('DEFAULT/rabbit_use_ssl').with_value('false')
-      should contain_keystone_config('DEFAULT/kombu_ssl_ca_certs').with_ensure('absent')
-      should contain_keystone_config('DEFAULT/kombu_ssl_certfile').with_ensure('absent')
-      should contain_keystone_config('DEFAULT/kombu_ssl_keyfile').with_ensure('absent')
-      should contain_keystone_config('DEFAULT/kombu_ssl_version').with_ensure('absent')
+      is_expected.to contain_keystone_config('DEFAULT/rabbit_use_ssl').with_value('false')
+      is_expected.to contain_keystone_config('DEFAULT/kombu_ssl_ca_certs').with_ensure('absent')
+      is_expected.to contain_keystone_config('DEFAULT/kombu_ssl_certfile').with_ensure('absent')
+      is_expected.to contain_keystone_config('DEFAULT/kombu_ssl_keyfile').with_ensure('absent')
+      is_expected.to contain_keystone_config('DEFAULT/kombu_ssl_version').with_ensure('absent')
+    end
+  end
+
+  describe 'when configuring max_token_size' do
+    let :params do
+      default_params.merge({:max_token_size => '16384' })
     end
+
+    it { is_expected.to contain_keystone_config('DEFAULT/max_token_size').with_value(params[:max_token_size]) }
   end
 
   describe 'setting notification settings' do
@@ -709,13 +670,15 @@ describe 'keystone' do
       default_params.merge({
         :notification_driver   => 'keystone.openstack.common.notifier.rpc_notifier',
         :notification_topics   => 'notifications',
+        :notification_format   => 'cadf',
         :control_exchange      => 'keystone'
       })
     end
 
-    it { should contain_keystone_config('DEFAULT/notification_driver').with_value('keystone.openstack.common.notifier.rpc_notifier') }
-    it { should contain_keystone_config('DEFAULT/notification_topics').with_value('notifications') }
-    it { should contain_keystone_config('DEFAULT/control_exchange').with_value('keystone') }
+    it { is_expected.to contain_keystone_config('DEFAULT/notification_driver').with_value('keystone.openstack.common.notifier.rpc_notifier') }
+    it { is_expected.to contain_keystone_config('DEFAULT/notification_topics').with_value('notifications') }
+    it { is_expected.to contain_keystone_config('DEFAULT/notification_format').with_value('cadf') }
+    it { is_expected.to contain_keystone_config('DEFAULT/control_exchange').with_value('keystone') }
   end
 
   describe 'setting sql (default) catalog' do
@@ -723,7 +686,7 @@ describe 'keystone' do
       default_params
     end
 
-    it { should contain_keystone_config('catalog/driver').with_value('keystone.catalog.backends.sql.Catalog') }
+    it { is_expected.to contain_keystone_config('catalog/driver').with_value('keystone.catalog.backends.sql.Catalog') }
   end
 
   describe 'setting default template catalog' do
@@ -734,8 +697,8 @@ describe 'keystone' do
       }
     end
 
-    it { should contain_keystone_config('catalog/driver').with_value('keystone.catalog.backends.templated.Catalog') }
-    it { should contain_keystone_config('catalog/template_file').with_value('/etc/keystone/default_catalog.templates') }
+    it { is_expected.to contain_keystone_config('catalog/driver').with_value('keystone.catalog.backends.templated.Catalog') }
+    it { is_expected.to contain_keystone_config('catalog/template_file').with_value('/etc/keystone/default_catalog.templates') }
   end
 
   describe 'with overridden validation_auth_url' do
@@ -748,8 +711,8 @@ describe 'keystone' do
       }
     end
 
-    it { should contain_keystone_config('DEFAULT/admin_endpoint').with_value('http://some.host:35357') }
-    it { should contain_class('keystone::service').with(
+    it { is_expected.to contain_keystone_config('DEFAULT/admin_endpoint').with_value('http://some.host:35357') }
+    it { is_expected.to contain_class('keystone::service').with(
       'validate'       => true,
       'admin_endpoint' => 'http://some.host:35357/v2.0'
     )}
@@ -764,7 +727,7 @@ describe 'keystone' do
       }
     end
 
-    it { should contain_class('keystone::service').with(
+    it { is_expected.to contain_class('keystone::service').with(
       'validate'       => true,
       'admin_endpoint' => 'http://some.host:35357'
     )}
@@ -779,8 +742,8 @@ describe 'keystone' do
       }
     end
 
-    it { should contain_keystone_config('catalog/driver').with_value('keystone.catalog.backends.templated.Catalog') }
-    it { should contain_keystone_config('catalog/template_file').with_value('/some/template_file') }
+    it { is_expected.to contain_keystone_config('catalog/driver').with_value('keystone.catalog.backends.templated.Catalog') }
+    it { is_expected.to contain_keystone_config('catalog/template_file').with_value('/some/template_file') }
   end
 
   describe 'setting service_provider' do
@@ -796,7 +759,7 @@ describe 'keystone' do
         { 'admin_token'    => 'service_token' }
       end
 
-      it { should contain_service('keystone').with(
+      it { is_expected.to contain_service('keystone').with(
         :provider => nil
       )}
     end
@@ -809,9 +772,111 @@ describe 'keystone' do
         }
       end
 
-      it { should contain_service('keystone').with(
+      it { is_expected.to contain_service('keystone').with(
         :provider => 'pacemaker'
       )}
     end
   end
+
+  describe 'when using fernet tokens' do
+    describe 'when enabling fernet_setup' do
+      let :params do
+        default_params.merge({
+          'enable_fernet_setup'    => true,
+          'fernet_max_active_keys' => 5,
+        })
+      end
+
+      it { is_expected.to contain_exec('keystone-manage fernet_setup').with(
+        :creates => '/etc/keystone/fernet-keys/0'
+      ) }
+      it { is_expected.to contain_keystone_config('fernet_tokens/max_active_keys').with_value(5)}
+    end
+
+    describe 'when overriding the fernet key directory' do
+      let :params do
+        default_params.merge({
+          'enable_fernet_setup'   => true,
+          'fernet_key_repository' => '/var/lib/fernet-keys',
+        })
+      end
+      it { is_expected.to contain_exec('keystone-manage fernet_setup').with(
+        :creates => '/var/lib/fernet-keys/0'
+      ) }
+
+    end
+  end
+
+  describe 'when configuring paste_deploy' do
+    describe 'with default paste config on Debian' do
+      let :params do
+        default_params
+      end
+
+      it { is_expected.to contain_keystone_config('paste_deploy/config_file').with_ensure('absent')}
+    end
+
+    describe 'with default paste config on RedHat' do
+      let :facts do
+        global_facts.merge({
+          :osfamily               => 'RedHat',
+          :operatingsystemrelease => '6.0'
+        })
+      end
+      let :params do
+        default_params
+      end
+
+      it { is_expected.to contain_keystone_config('paste_deploy/config_file').with_value(
+          '/usr/share/keystone/keystone-dist-paste.ini'
+      )}
+    end
+
+    describe 'with overrided paste_deploy' do
+      let :params do
+        default_params.merge({
+          'paste_config'    => '/usr/share/keystone/keystone-paste.ini',
+        })
+      end
+
+      it { is_expected.to contain_keystone_config('paste_deploy/config_file').with_value(
+          '/usr/share/keystone/keystone-paste.ini'
+      )}
+    end
+  end
+
+  context 'on RedHat platforms' do
+    let :facts do
+      global_facts.merge({
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '7.0'
+      })
+    end
+
+    let :platform_parameters do
+      {
+        :service_name => 'openstack-keystone'
+      }
+    end
+
+    it_configures 'when using default class parameters for httpd'
+  end
+
+  context 'on Debian platforms' do
+    let :facts do
+      global_facts.merge({
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Debian',
+        :operatingsystemrelease => '7.0'
+      })
+    end
+
+    let :platform_parameters do
+      {
+        :service_name => 'keystone'
+      }
+    end
+
+    it_configures 'when using default class parameters for httpd'
+  end
 end
index f2a22d619a5572c983e890a2e1e52c35670ad16f..19423954577a097f6192eabacd383a94e7b05414 100644 (file)
@@ -17,22 +17,22 @@ describe 'keystone::wsgi::apache' do
   end
 
   shared_examples_for 'apache serving keystone with mod_wsgi' do
-    it { should contain_service('httpd').with_name(platform_parameters[:httpd_service_name]) }
-    it { should contain_class('keystone::params') }
-    it { should contain_class('apache') }
-    it { should contain_class('apache::mod::wsgi') }
-    it { should contain_class('keystone::db::sync') }
+    it { is_expected.to contain_service('httpd').with_name(platform_parameters[:httpd_service_name]) }
+    it { is_expected.to contain_class('keystone::params') }
+    it { is_expected.to contain_class('apache') }
+    it { is_expected.to contain_class('apache::mod::wsgi') }
+    it { is_expected.to contain_class('keystone::db::sync') }
 
     describe 'with default parameters' do
 
-      it { should contain_file("#{platform_parameters[:wsgi_script_path]}").with(
+      it { is_expected.to contain_file("#{platform_parameters[:wsgi_script_path]}").with(
         'ensure'  => 'directory',
         'owner'   => 'keystone',
         'group'   => 'keystone',
         'require' => 'Package[httpd]'
       )}
 
-      it { should contain_file('keystone_wsgi_admin').with(
+      it { is_expected.to contain_file('keystone_wsgi_admin').with(
         'ensure'  => 'file',
         'path'    => "#{platform_parameters[:wsgi_script_path]}/admin",
         'source'  => platform_parameters[:wsgi_script_source],
@@ -42,7 +42,7 @@ describe 'keystone::wsgi::apache' do
         'require' => ["File[#{platform_parameters[:wsgi_script_path]}]", "Package[keystone]"]
       )}
 
-      it { should contain_file('keystone_wsgi_main').with(
+      it { is_expected.to contain_file('keystone_wsgi_main').with(
         'ensure'  => 'file',
         'path'    => "#{platform_parameters[:wsgi_script_path]}/main",
         'source'  => platform_parameters[:wsgi_script_source],
@@ -52,7 +52,7 @@ describe 'keystone::wsgi::apache' do
         'require' => ["File[#{platform_parameters[:wsgi_script_path]}]", "Package[keystone]"]
       )}
 
-      it { should contain_apache__vhost('keystone_wsgi_admin').with(
+      it { is_expected.to contain_apache__vhost('keystone_wsgi_admin').with(
         'servername'                  => 'some.host.tld',
         'ip'                          => nil,
         'port'                        => '35357',
@@ -73,7 +73,7 @@ describe 'keystone::wsgi::apache' do
         'require'                     => 'File[keystone_wsgi_admin]'
       )}
 
-      it { should contain_apache__vhost('keystone_wsgi_main').with(
+      it { is_expected.to contain_apache__vhost('keystone_wsgi_main').with(
         'servername'                  => 'some.host.tld',
         'ip'                          => nil,
         'port'                        => '5000',
@@ -93,7 +93,7 @@ describe 'keystone::wsgi::apache' do
         'wsgi_script_aliases'         => { '/' => "#{platform_parameters[:wsgi_script_path]}/main" },
         'require'                     => 'File[keystone_wsgi_main]'
       )}
-      it { should contain_file("#{platform_parameters[:httpd_ports_file]}") }
+      it { is_expected.to contain_file("#{platform_parameters[:httpd_ports_file]}") }
     end
 
     describe 'when overriding parameters using different ports' do
@@ -108,7 +108,7 @@ describe 'keystone::wsgi::apache' do
         }
       end
 
-      it { should contain_apache__vhost('keystone_wsgi_admin').with(
+      it { is_expected.to contain_apache__vhost('keystone_wsgi_admin').with(
         'servername'                  => 'dummy.host',
         'ip'                          => '10.42.51.1',
         'port'                        => '4142',
@@ -129,7 +129,7 @@ describe 'keystone::wsgi::apache' do
         'require'                     => 'File[keystone_wsgi_admin]'
       )}
 
-      it { should contain_apache__vhost('keystone_wsgi_main').with(
+      it { is_expected.to contain_apache__vhost('keystone_wsgi_main').with(
         'servername'                  => 'dummy.host',
         'ip'                          => '10.42.51.1',
         'port'                        => '12345',
@@ -150,7 +150,7 @@ describe 'keystone::wsgi::apache' do
         'require'                     => 'File[keystone_wsgi_main]'
       )}
 
-      it { should contain_file("#{platform_parameters[:httpd_ports_file]}") }
+      it { is_expected.to contain_file("#{platform_parameters[:httpd_ports_file]}") }
     end
 
     describe 'when overriding parameters using same port' do
@@ -166,9 +166,9 @@ describe 'keystone::wsgi::apache' do
         }
       end
 
-      it { should_not contain_apache__vhost('keystone_wsgi_admin') }
+      it { is_expected.to_not contain_apache__vhost('keystone_wsgi_admin') }
 
-      it { should contain_apache__vhost('keystone_wsgi_main').with(
+      it { is_expected.to contain_apache__vhost('keystone_wsgi_main').with(
         'servername'                  => 'dummy.host',
         'ip'                          => nil,
         'port'                        => '4242',
@@ -208,6 +208,35 @@ describe 'keystone::wsgi::apache' do
 
       it_raises 'a Puppet::Error', /When using the same port for public & private endpoints, public_path and admin_path should be different\./
     end
+
+    describe 'when overriding parameters using symlink and custom file source' do
+      let :params do
+        {
+          :wsgi_script_ensure => 'link',
+          :wsgi_script_source => '/opt/keystone/httpd/keystone.py',
+        }
+      end
+
+      it { is_expected.to contain_file('keystone_wsgi_admin').with(
+        'ensure'  => 'link',
+        'path'    => "#{platform_parameters[:wsgi_script_path]}/admin",
+        'target'  => '/opt/keystone/httpd/keystone.py',
+        'owner'   => 'keystone',
+        'group'   => 'keystone',
+        'mode'    => '0644',
+        'require' => ["File[#{platform_parameters[:wsgi_script_path]}]", "Package[keystone]"]
+      )}
+
+      it { is_expected.to contain_file('keystone_wsgi_main').with(
+        'ensure'  => 'link',
+        'path'    => "#{platform_parameters[:wsgi_script_path]}/main",
+        'target'  => '/opt/keystone/httpd/keystone.py',
+        'owner'   => 'keystone',
+        'group'   => 'keystone',
+        'mode'    => '0644',
+        'require' => ["File[#{platform_parameters[:wsgi_script_path]}]", "Package[keystone]"]
+      )}
+    end
   end
 
   context 'on RedHat platforms' do
index d7d0a62c5ac771ad5705e2c5fe883545c5249c67..18979635eb7801ef2d1d97a2d2fbdcc8f9d54a01 100644 (file)
@@ -36,25 +36,25 @@ describe 'keystone::resource::service_identity' do
         required_params
       end
 
-      it { should contain_keystone_user(title).with(
+      it { is_expected.to contain_keystone_user(title).with(
         :ensure   => 'present',
         :password => 'secrete',
         :email    => 'neutron@localhost',
         :tenant   => 'services',
       )}
 
-      it { should contain_keystone_user_role("#{title}@services").with(
+      it { is_expected.to contain_keystone_user_role("#{title}@services").with(
         :ensure => 'present',
-        :roles  => 'admin',
+        :roles  => ['admin'],
       )}
 
-      it { should contain_keystone_service(title).with(
+      it { is_expected.to contain_keystone_service(title).with(
         :ensure      => 'present',
         :type        => 'network',
         :description => 'neutron service',
       )}
 
-      it { should contain_keystone_endpoint("RegionOne/#{title}").with(
+      it { is_expected.to contain_keystone_endpoint("RegionOne/#{title}").with(
         :ensure       => 'present',
         :public_url   => 'http://7.7.7.7:9696',
         :internal_url => 'http://10.0.0.1:9696',
@@ -66,7 +66,7 @@ describe 'keystone::resource::service_identity' do
       let :params do
         required_params.delete(:password)
       end
-      it { expect { should raise_error(Puppet::Error) } }
+      it { expect { is_expected.to raise_error(Puppet::Error) } }
     end
 
   end
index d92156a3618e079ee5ee5f1b86edca31c09bdee7..fec0eacc9826a60e94ab517f68ec7b21f9d36248 100644 (file)
@@ -1,5 +1,5 @@
 shared_examples_for "a Puppet::Error" do |description|
   it "with message matching #{description.inspect}" do
-    expect { should have_class_count(1) }.to raise_error(Puppet::Error, description)
+    expect { is_expected.to have_class_count(1) }.to raise_error(Puppet::Error, description)
   end
 end
index a6c4788bdda6f4ea276def668c2a25fe99d8f8d6..78594f8ae72abbc22e53932920130f004142650d 100644 (file)
@@ -4,7 +4,6 @@ require 'puppetlabs_spec_helper/module_spec_helper'
 require 'shared_examples'
 
 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.alias_it_should_behave_like_to :it_configures, 'configures'
+  c.alias_it_should_behave_like_to :it_raises, 'raises'
 end
-
diff --git a/3rdparty/modules/keystone/spec/spec_helper_acceptance.rb b/3rdparty/modules/keystone/spec/spec_helper_acceptance.rb
new file mode 100644 (file)
index 0000000..2c2634a
--- /dev/null
@@ -0,0 +1,42 @@
+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__), '..'))
+
+  # 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'
+
+      # clean out any module cruft
+      shell('rm -fr /etc/puppet/modules/*')
+
+      # install library modules from the forge
+      on host, puppet('module','install','puppetlabs-mysql'), { :acceptable_exit_codes => 0 }
+      on host, puppet('module','install','dprince/qpid'), { :acceptable_exit_codes => 0 }
+      on host, puppet('module','install','duritong/sysctl'), { :acceptable_exit_codes => 0 }
+      on host, puppet('module','install','puppetlabs-inifile'), { :acceptable_exit_codes => 0 }
+      on host, puppet('module','install','puppetlabs-rabbitmq'), { :acceptable_exit_codes => 0 }
+      on host, puppet('module','install','puppetlabs-apache'), { :acceptable_exit_codes => 0 }
+
+      # install puppet modules from git, use master
+      shell('git clone https://git.openstack.org/openstack/puppet-openstacklib /etc/puppet/modules/openstacklib')
+      shell('git clone https://git.openstack.org/openstack/puppet-openstack_extras /etc/puppet/modules/openstack_extras')
+
+      # Install the module being tested
+      puppet_module_install(:source => proj_root, :module_name => 'keystone')
+      # List modules installed to help with debugging
+      on hosts[0], puppet('module','list'), { :acceptable_exit_codes => 0 }
+    end
+  end
+end
index a0ac7523ec9c3e26531b7157855eba4597ddaa09..9ca5b436f3594557d011a30fc6b0f06027933ab8 100644 (file)
@@ -6,7 +6,14 @@ provider_class = Puppet::Type.type(:keystone_endpoint).provider(:openstack)
 
 describe provider_class do
 
-  describe 'when updating an endpoint' do
+  shared_examples 'authenticated with environment variables' do
+    ENV['OS_USERNAME']     = 'test'
+    ENV['OS_PASSWORD']     = 'abc123'
+    ENV['OS_PROJECT_NAME'] = 'test'
+    ENV['OS_AUTH_URL']     = 'http://127.0.0.1:35357/v2.0'
+  end
+
+  describe 'when managing an endpoint' do
 
     let(:endpoint_attrs) do
       {
@@ -15,12 +22,6 @@ describe provider_class do
         :public_url   => 'http://127.0.0.1:5000/v2.0',
         :internal_url => 'http://127.0.0.1:5001/v2.0',
         :admin_url    => 'http://127.0.0.1:5002/v2.0',
-        :auth         => {
-          'username'    => 'test',
-          'password'    => 'abc123',
-          'tenant_name' => 'foo',
-          'auth_url'    => 'http://127.0.0.1:5000/v2.0',
-        }
       }
     end
 
@@ -32,16 +33,17 @@ describe provider_class do
       provider_class.new(resource)
     end
 
-    describe '#create' do
-      it 'creates an endpoint' do
-        provider.class.stubs(:openstack)
-                      .with('endpoint', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Region","Service Name","Service Type","PublicURL","AdminURL","InternalURL"
+    it_behaves_like 'authenticated with environment variables' do
+      describe '#create' do
+        it 'creates an endpoint' do
+          provider.class.stubs(:openstack)
+                        .with('endpoint', 'list', '--quiet', '--format', 'csv', '--long')
+                        .returns('"ID","Region","Service Name","Service Type","PublicURL","AdminURL","InternalURL"
 "1cb05cfed7c24279be884ba4f6520262","foo","bar","","http://127.0.0.1:5000/v2.0","http://127.0.0.1:5001/v2.0","http://127.0.0.1:5002/v2.0"
 ')
-        provider.class.stubs(:openstack)
-                      .with('endpoint', 'create', '--format', 'shell', [['bar', '--region', 'foo', '--publicurl', 'http://127.0.0.1:5000/v2.0', '--internalurl', 'http://127.0.0.1:5001/v2.0', '--adminurl', 'http://127.0.0.1:5002/v2.0', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('adminurl="http://127.0.0.1:5002/v2.0"
+          provider.class.stubs(:openstack)
+                        .with('endpoint', 'create', '--format', 'shell', ['bar', '--region', 'foo', '--publicurl', 'http://127.0.0.1:5000/v2.0', '--internalurl', 'http://127.0.0.1:5001/v2.0', '--adminurl', 'http://127.0.0.1:5002/v2.0'])
+                        .returns('adminurl="http://127.0.0.1:5002/v2.0"
 id="3a5c4378981e4112a0d44902a43e16ef"
 internalurl="http://127.0.0.1:5001/v2.0"
 publicurl="http://127.0.0.1:5000/v2.0"
@@ -50,64 +52,49 @@ service_id="8137d72980fd462192f276585a002426"
 service_name="bar"
 service_type="test"
 ')
-        provider.create
-        expect(provider.exists?).to be_truthy
-      end
-    end
-
-    describe '#destroy' do
-      it 'destroys an endpoint' do
-        provider.class.stubs(:openstack)
-                      .with('endpoint', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Region","Service Name","Service Type","PublicURL","AdminURL","InternalURL"
-"1cb05cfed7c24279be884ba4f6520262","foo","bar","","http://127.0.0.1:5000/v2.0","http://127.0.0.1:5001/v2.0","http://127.0.0.1:5002/v2.0"
-')
-        provider.class.stubs(:openstack)
-                      .with('endpoint', 'delete', [['1cb05cfed7c24279be884ba4f6520262', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-        expect(provider.destroy).to be_nil # We don't really care that it's nil, only that it runs successfully
+          provider.create
+          expect(provider.exists?).to be_truthy
+        end
       end
 
-    end
-
-    describe '#exists' do
-      context 'when endpoint exists' do
-
-        subject(:response) do
+      describe '#destroy' do
+        it 'destroys an endpoint' do
           provider.class.stubs(:openstack)
-                        .with('endpoint', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
+                        .with('endpoint', 'list', '--quiet', '--format', 'csv', '--long')
                         .returns('"ID","Region","Service Name","Service Type","PublicURL","AdminURL","InternalURL"
-"1cb05cfed7c24279be884ba4f6520262","foo","bar","","http://127.0.0.1:5000/v2.0","http://127.0.0.1:5001/v2.0","http://127.0.0.1:5002/v2.0"
+"1cb05cfed7c24279be884ba4f6520262","foo","bar","test","http://127.0.0.1:5000/v2.0","http://127.0.0.1:5001/v2.0","http://127.0.0.1:5002/v2.0"
 ')
-          response = provider.exists?
+          provider.class.stubs(:openstack)
+                        .with('endpoint', 'delete', [])
+          provider.destroy
+          expect(provider.exists?).to be_falsey
         end
-
-        it { is_expected.to be_truthy }
       end
 
-      context 'when tenant does not exist' do
+      describe '#exists' do
+        context 'when tenant does not exist' do
+          subject(:response) do
+            provider.class.stubs(:openstack)
+                          .with('endpoint', 'list', '--quiet', '--format', 'csv', '--long')
+                          .returns('"ID","Region","Service Name","Service Type","PublicURL","AdminURL","InternalURL"')
+            response = provider.exists?
+          end
 
-        subject(:response) do
-          provider.class.stubs(:openstack)
-                        .with('endpoint', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                        .returns('"ID","Region","Service Name","Service Type","PublicURL","AdminURL","InternalURL"')
-          response = provider.exists?
+          it { is_expected.to be_falsey }
         end
-
-        it { is_expected.to be_falsey }
       end
-    end
 
-    describe '#instances' do
-      it 'finds every tenant' do
-        provider.class.stubs(:openstack)
-                      .with('endpoint', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Region","Service Name","Service Type","PublicURL","AdminURL","InternalURL"
-"1cb05cfed7c24279be884ba4f6520262","foo","bar","","http://127.0.0.1:5000/v2.0","http://127.0.0.1:5001/v2.0","http://127.0.0.1:5002/v2.0"
+      describe '#instances' do
+        it 'finds every tenant' do
+          provider.class.stubs(:openstack)
+                        .with('endpoint', 'list', '--quiet', '--format', 'csv', '--long')
+                        .returns('"ID","Region","Service Name","Service Type","PublicURL","AdminURL","InternalURL"
+"3a5c4378981e4112a0d44902a43e16ef","foo","bar","test","http://127.0.0.1:5000/v2.0","http://127.0.0.1:5001/v2.0","http://127.0.0.1:5002/v2.0"
 ')
-        instances = provider.instances
-        expect(instances.count).to eq(1)
+          instances = Puppet::Type::Keystone_endpoint::ProviderOpenstack.instances
+          expect(instances.count).to eq(1)
+        end
       end
     end
-
   end
 end
index 179574fea3b4b9c98635b131721b8ade8287ef58..09e229b82fc1ada90e13ec2f0b41c8425d8dfc27 100644 (file)
@@ -6,96 +6,81 @@ provider_class = Puppet::Type.type(:keystone_role).provider(:openstack)
 
 describe provider_class do
 
-  describe 'when creating a role' do
+  shared_examples 'authenticated with environment variables' do
+    ENV['OS_USERNAME']     = 'test'
+    ENV['OS_PASSWORD']     = 'abc123'
+    ENV['OS_PROJECT_NAME'] = 'test'
+    ENV['OS_AUTH_URL']     = 'http://127.0.0.1:5000'
+  end
 
-    let(:role_attrs) do
-      {
-        :name         => 'foo',
-        :ensure       => 'present',
-        :auth         => {
-          'username'    => 'test',
-          'password'    => 'abc123',
-          'tenant_name' => 'foo',
-          'auth_url'    => 'http://127.0.0.1:5000/v2.0',
+  describe 'when creating a role' do
+    it_behaves_like 'authenticated with environment variables' do
+      let(:role_attrs) do
+        {
+          :name         => 'foo',
+          :ensure       => 'present',
         }
-      }
-    end
-
-    let(:resource) do
-      Puppet::Type::Keystone_role.new(role_attrs)
-    end
-
-    let(:provider) do
-      provider_class.new(resource)
-    end
-
-    describe '#create' do
-      it 'creates a role' do
-        provider.class.stubs(:openstack)
-                      .with('role', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name"
-"1cb05cfed7c24279be884ba4f6520262","foo"
-')
-        provider.class.stubs(:openstack)
-                      .with('role', 'create', '--format', 'shell', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('name="foo"')
-        provider.create
-        expect(provider.exists?).to be_truthy
       end
-    end
 
-    describe '#destroy' do
-      it 'destroys a role' do
-        provider.class.stubs(:openstack)
-                      .with('role', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name"')
-        provider.class.stubs(:openstack)
-                      .with('role', 'delete', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-        provider.destroy
-        expect(provider.exists?).to be_falsey
+      let(:resource) do
+        Puppet::Type::Keystone_role.new(role_attrs)
       end
 
-    end
-
-    describe '#exists' do
-      context 'when role exists' do
+      let(:provider) do
+        provider_class.new(resource)
+      end
 
-        subject(:response) do
+      describe '#create' do
+        it 'creates a role' do
           provider.class.stubs(:openstack)
-                        .with('role', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
+                        .with('role', 'list', '--quiet', '--format', 'csv', [])
                         .returns('"ID","Name"
 "1cb05cfed7c24279be884ba4f6520262","foo"
 ')
-          response = provider.exists?
+          provider.class.stubs(:openstack)
+                        .with('role', 'create', '--format', 'shell', 'foo')
+                        .returns('name="foo"')
+          provider.create
+          expect(provider.exists?).to be_truthy
         end
-
-        it { is_expected.to be_truthy }
       end
 
-      context 'when role does not exist' do
-
-        subject(:response) do
+      describe '#destroy' do
+        it 'destroys a role' do
           provider.class.stubs(:openstack)
-                        .with('role', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name"')
-          response = provider.exists?
+                        .with('role', 'list', '--quiet', '--format', 'csv', [])
+                        .returns('"ID","Name"')
+          provider.class.stubs(:openstack)
+                        .with('role', 'delete', [])
+          provider.destroy
+          expect(provider.exists?).to be_falsey
         end
 
-        it { is_expected.to be_falsey }
       end
-    end
 
-    describe '#instances' do
-      it 'finds every role' do
-        provider.class.stubs(:openstack)
-                      .with('role', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name"
+      describe '#exists' do
+        context 'when role does not exist' do
+          subject(:response) do
+            provider.class.stubs(:openstack)
+                          .with('role', 'list', '--quiet', '--format', 'csv', [])
+                        .returns('"ID","Name"')
+            response = provider.exists?
+          end
+          it { is_expected.to be_falsey }
+        end
+      end
+
+      describe '#instances' do
+        it 'finds every role' do
+          provider.class.stubs(:openstack)
+                        .with('role', 'list', '--quiet', '--format', 'csv', [])
+                        .returns('"ID","Name"
 "1cb05cfed7c24279be884ba4f6520262","foo"
 ')
-        instances = provider.instances
-        expect(instances.count).to eq(1)
+          instances = Puppet::Type::Keystone_role::ProviderOpenstack.instances
+          expect(instances.count).to eq(1)
+        end
       end
     end
-
   end
 end
index 5b9814f9107911d50bf1975a82977ba853311ff9..5a299a5b4746a5ded9cc7d36b46962fe177d2225 100644 (file)
@@ -6,7 +6,14 @@ provider_class = Puppet::Type.type(:keystone_service).provider(:openstack)
 
 describe provider_class do
 
-  describe 'when creating a service' do
+  shared_examples 'authenticated with environment variables' do
+    ENV['OS_USERNAME']     = 'test'
+    ENV['OS_PASSWORD']     = 'abc123'
+    ENV['OS_PROJECT_NAME'] = 'test'
+    ENV['OS_AUTH_URL']     = 'http://127.0.0.1:35357/v2.0'
+  end
+
+  describe 'when managing a service' do
 
     let(:service_attrs) do
       {
@@ -14,12 +21,6 @@ describe provider_class do
         :description  => 'foo',
         :ensure       => 'present',
         :type         => 'foo',
-        :auth         => {
-          'username'    => 'test',
-          'password'    => 'abc123',
-          'tenant_name' => 'foo',
-          'auth_url'    => 'http://127.0.0.1:5000/v2.0',
-        }
       }
     end
 
@@ -31,78 +32,62 @@ describe provider_class do
       provider_class.new(resource)
     end
 
-    describe '#create' do
-      it 'creates a service' do
-        provider.class.stubs(:openstack)
-                      .with('service', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Type","Description"
+    it_behaves_like 'authenticated with environment variables' do
+      describe '#create' do
+        it 'creates a service' do
+          provider.class.stubs(:openstack)
+                        .with('service', 'list', '--quiet', '--format', 'csv', '--long')
+                        .returns('"ID","Name","Type","Description"
 "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo"
 ')
-        provider.class.stubs(:openstack)
-                      .with('service', 'create', '--format', 'shell', [['foo', '--description', 'foo', '--type', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('description="foo"
+          provider.class.stubs(:openstack)
+                        .with('service', 'create', '--format', 'shell', ['--description', 'foo', '--type', 'foo', 'foo'])
+                        .returns('description="foo"
 enabled="True"
 id="8f0dd4c0abc44240998fbb3f5089ecbf"
 name="foo"
 type="foo"
 ')
-        provider.create
-        expect(provider.exists?).to be_truthy
-      end
-    end
-
-    describe '#destroy' do
-      it 'destroys a service' do
-        provider.class.stubs(:openstack)
-                      .with('service', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Type","Description"')
-        provider.class.stubs(:openstack)
-                      .with('service', 'delete', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-        provider.destroy
-        expect(provider.exists?).to be_falsey
+          provider.create
+          expect(provider.exists?).to be_truthy
+        end
       end
 
-    end
-
-    describe '#exists' do
-      context 'when service exists' do
-
-        subject(:response) do
+      describe '#destroy' do
+        it 'destroys a service' do
           provider.class.stubs(:openstack)
-                        .with('service', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
+                        .with('service', 'list', '--quiet', '--format', 'csv', '--long')
                         .returns('"ID","Name","Type","Description"
 "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo"
 ')
-          response = provider.exists?
-        end
-
-        it { is_expected.to be_truthy }
-      end
-
-      context 'when service does not exist' do
-
-        subject(:response) do
           provider.class.stubs(:openstack)
-                        .with('service', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                        .returns('"ID","Name","Type","Description"')
-          response = provider.exists?
+                        .with('service', 'delete', [])
+          provider.destroy
+          expect(provider.exists?).to be_falsey
         end
 
-        it { is_expected.to be_falsey }
+        context 'when service does not exist' do
+          subject(:response) do
+            provider.class.stubs(:openstack)
+                          .with('service', 'list', '--quiet', '--format', 'csv', '--long')
+                          .returns('"ID","Name","Type","Description"')
+            response = provider.exists?
+          end
+          it { is_expected.to be_falsey }
+        end
       end
-    end
 
-    describe '#instances' do
-      it 'finds every service' do
-        provider.class.stubs(:openstack)
-                      .with('service', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Type","Description"
-"1cb05cfed7c24279be884ba4f6520262","foo","foo","foo"
+      describe '#instances' do
+        it 'finds every service' do
+          provider.class.stubs(:openstack)
+                        .with('service', 'list', '--quiet', '--format', 'csv', '--long')
+                        .returns('"ID","Name","Type","Description"
+"8f0dd4c0abc44240998fbb3f5089ecbf","foo","foo","foo"
 ')
-        instances = provider.instances
-        expect(instances.count).to eq(1)
+          instances = Puppet::Type::Keystone_service::ProviderOpenstack.instances
+          expect(instances.count).to eq(1)
+        end
       end
     end
-
   end
 end
index de9ceb0d1893a19075d31ae0b4dc637838bcc568..4981f1e5ce2ba6ad2cb7a589c7d6d9d921418581 100644 (file)
@@ -3,10 +3,11 @@ require 'spec_helper'
 require 'puppet/provider/keystone'
 require 'tempfile'
 
-
 klass = Puppet::Provider::Keystone
 
 class Puppet::Provider::Keystone
+  @credentials = Puppet::Provider::Openstack::CredentialsV2_0.new
+
   def self.reset
     @admin_endpoint = nil
     @tenant_hash    = nil
@@ -21,20 +22,15 @@ describe Puppet::Provider::Keystone do
     klass.reset
   end
 
-
   describe 'when retrieving the security token' do
-
     it 'should return nothing if there is no keystone config file' do
-      ini_file = Puppet::Util::IniConfig::File.new
-      t = Tempfile.new('foo')
-      path = t.path
-      t.unlink
-      ini_file.read(path)
+      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_token).to be_nil
@@ -42,6 +38,7 @@ describe Puppet::Provider::Keystone do
 
     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_token).to be_nil
@@ -49,65 +46,74 @@ describe Puppet::Provider::Keystone do
 
     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')
-      klass.get_admin_token.should == 'foo'
+      expect(klass.get_admin_token).to eq('foo')
     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' }}
+      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')
-      klass.get_admin_endpoint.should == 'http://192.168.56.210:35357/v2.0/'
+      expect(klass.get_admin_endpoint).to eq('http://192.168.56.210:35357/v2.0/')
     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' }}
+      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')
-      klass.get_admin_endpoint.should == 'http://127.0.0.1:35357/v2.0/'
+      expect(klass.get_admin_endpoint).to eq('http://127.0.0.1:35357/v2.0/')
     end
 
     it 'should use [::1] in the admin endpoint if bind_host is ::0' do
       mock = {'DEFAULT' => { 'admin_bind_host' => '::0', 'admin_port' => '35357' }}
+      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')
-      klass.get_admin_endpoint.should == 'http://[::1]:35357/v2.0/'
+      expect(klass.get_admin_endpoint).to eq('http://[::1]:35357/v2.0/')
     end
 
     it 'should use localhost in the admin endpoint if bind_host is unspecified' do
       mock = {'DEFAULT' => { 'admin_port' => '35357' }}
+      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')
-      klass.get_admin_endpoint.should == 'http://127.0.0.1:35357/v2.0/'
+      expect(klass.get_admin_endpoint).to eq('http://127.0.0.1:35357/v2.0/')
     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'}}
+      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')
-      klass.get_admin_endpoint.should == 'https://192.168.56.210:35357/v2.0/'
+      expect(klass.get_admin_endpoint).to eq('https://192.168.56.210:35357/v2.0/')
     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'}}
+      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')
-      klass.get_admin_endpoint.should == 'http://192.168.56.210:35357/v2.0/'
+      expect(klass.get_admin_endpoint).to eq('http://192.168.56.210:35357/v2.0/')
     end
 
     it 'should use the defined admin_endpoint if available' do
       mock = {'DEFAULT' => {'admin_endpoint' => 'https://keystone.example.com' }, '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')
-      klass.get_admin_endpoint.should == 'https://keystone.example.com/v2.0/'
+      expect(klass.get_admin_endpoint).to eq('https://keystone.example.com/v2.0/')
     end
 
     it 'should handle an admin_endpoint with a trailing slash' do
       mock = {'DEFAULT' => {'admin_endpoint' => 'https://keystone.example.com/' }, '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')
-      klass.get_admin_endpoint.should == 'https://keystone.example.com/v2.0/'
+      expect(klass.get_admin_endpoint).to eq('https://keystone.example.com/v2.0/')
     end
 
   end
index 11861fc8b26fde7e5c5fc6ec13582cf2bb37640e..1dec49e0603027fa4d0033c990ba0c991fca38cd 100644 (file)
@@ -6,7 +6,14 @@ provider_class = Puppet::Type.type(:keystone_tenant).provider(:openstack)
 
 describe provider_class do
 
-  describe 'when updating a tenant' do
+  shared_examples 'authenticated with environment variables' do
+    ENV['OS_USERNAME']     = 'test'
+    ENV['OS_PASSWORD']     = 'abc123'
+    ENV['OS_PROJECT_NAME'] = 'test'
+    ENV['OS_AUTH_URL']     = 'http://127.0.0.1:35357/v2.0'
+  end
+
+  describe 'when managing a tenant' do
 
     let(:tenant_attrs) do
       {
@@ -14,12 +21,6 @@ describe provider_class do
         :description  => 'foo',
         :ensure       => 'present',
         :enabled      => 'True',
-        :auth         => {
-          'username'    => 'test',
-          'password'    => 'abc123',
-          'tenant_name' => 'foo',
-          'auth_url'    => 'http://127.0.0.1:5000/v2.0',
-        }
       }
     end
 
@@ -31,76 +32,59 @@ describe provider_class do
       provider_class.new(resource)
     end
 
-    describe '#create' do
-      it 'creates a tenant' do
-        provider.class.stubs(:openstack)
-                      .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Description","Enabled"
+    it_behaves_like 'authenticated with environment variables' do
+      describe '#create' do
+        it 'creates a tenant' do
+          provider.class.stubs(:openstack)
+                        .with('project', 'list', '--quiet', '--format', 'csv', '--long')
+                        .returns('"ID","Name","Description","Enabled"
 "1cb05cfed7c24279be884ba4f6520262","foo","foo",True
 ')
-        provider.class.stubs(:openstack)
-                      .with('project', 'create', '--format', 'shell', [['foo', '--enable', '--description', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('description="foo"
+          provider.class.stubs(:openstack)
+                        .with('project', 'create', '--format', 'shell', ['foo', '--enable', '--description', 'foo'])
+                        .returns('description="foo"
 enabled="True"
 name="foo"
 ')
-        provider.create
-        expect(provider.exists?).to be_truthy
-      end
-    end
-
-    describe '#destroy' do
-      it 'destroys a tenant' do
-        provider.class.stubs(:openstack)
-                      .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Description","Enabled"')
-        provider.class.stubs(:openstack)
-                      .with('project', 'delete', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-        provider.destroy
-        expect(provider.exists?).to be_falsey
+          provider.create
+          expect(provider.exists?).to be_truthy
+        end
       end
 
-    end
-
-    describe '#exists' do
-      context 'when tenant exists' do
-
-        subject(:response) do
+      describe '#destroy' do
+        it 'destroys a tenant' do
           provider.class.stubs(:openstack)
-                        .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                        .returns('"ID","Name","Description","Enabled"
-"1cb05cfed7c24279be884ba4f6520262","foo","foo",True
-')
-          response = provider.exists?
+                        .with('project', 'list', '--quiet', '--format', 'csv', '--long')
+                        .returns('"ID","Name","Description","Enabled"')
+          provider.class.stubs(:openstack)
+                        .with('project', 'delete', [])
+          provider.destroy
+          expect(provider.exists?).to be_falsey
         end
-
-        it { is_expected.to be_truthy }
       end
 
       context 'when tenant does not exist' do
-
         subject(:response) do
           provider.class.stubs(:openstack)
-                        .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Description","Enabled"')
+                        .with('project', 'list', '--quiet', '--format', 'csv', '--long')
+                        .returns('"ID","Name","Description","Enabled"')
           response = provider.exists?
         end
 
         it { is_expected.to be_falsey }
       end
-    end
 
-    describe '#instances' do
-      it 'finds every tenant' do
-        provider.class.stubs(:openstack)
-                      .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Description","Enabled"
+      describe '#instances' do
+        it 'finds every tenant' do
+          provider.class.stubs(:openstack)
+                        .with('project', 'list', '--quiet', '--format', 'csv', '--long')
+                       .returns('"ID","Name","Description","Enabled"
 "1cb05cfed7c24279be884ba4f6520262","foo","foo",True
 ')
-        instances = provider.instances
-        expect(instances.count).to eq(1)
+          instances = Puppet::Type::Keystone_tenant::ProviderOpenstack.instances
+          expect(instances.count).to eq(1)
+        end
       end
     end
-
   end
 end
index 1a74c636cd2e868f12f6c1732aa49d94642e10fb..3f545d0cf131c5121f95ff8a5f29d13236ba7b7b 100644 (file)
@@ -6,20 +6,21 @@ provider_class = Puppet::Type.type(:keystone_user).provider(:openstack)
 
 describe provider_class do
 
+  shared_examples 'authenticated with environment variables' do
+    ENV['OS_USERNAME']     = 'test'
+    ENV['OS_PASSWORD']     = 'abc123'
+    ENV['OS_PROJECT_NAME'] = 'test'
+    ENV['OS_AUTH_URL']     = 'http://127.0.0.1:5000'
+  end
+
   let(:user_attrs) do
     {
       :name         => 'foo',
-      :ensure       => 'present',
+      :ensure       => :present,
       :enabled      => 'True',
       :password     => 'foo',
       :tenant       => 'foo',
       :email        => 'foo@example.com',
-      :auth         => {
-        'username'    => 'test',
-        'password'    => 'abc123',
-        'tenant_name' => 'foo',
-        'auth_url'    => 'http://127.0.0.1:5000/v2.0',
-      }
     }
   end
 
@@ -31,175 +32,180 @@ describe provider_class do
     provider_class.new(resource)
   end
 
-  describe 'when updating a user' do
-
-    describe '#create' do
-      it 'creates a user' do
-        provider.class.stubs(:openstack)
-                      .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Project","Email","Enabled"
+  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
 ')
-        provider.class.stubs(:openstack)
-                      .with('user', 'create', '--format', 'shell', [['foo', '--enable', '--password', 'foo', '--project', 'foo', '--email', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('email="foo@example.com"
+          provider.class.stubs(:openstack)
+                        .with('user', 'create', '--format', 'shell', ['foo', '--enable', '--password', 'foo', '--project', 'foo', '--email', 'foo@example.com'])
+                        .returns('email="foo@example.com"
 enabled="True"
 id="12b23f07d4a3448d8189521ab09610b0"
 name="foo"
 project_id="5e2001b2248540f191ff22627dc0c2d7"
 username="foo"
 ')
-        provider.create
-        expect(provider.exists?).to be_truthy
-      end
-    end
-
-    describe '#destroy' do
-      it 'destroys a user' do
-        provider.class.stubs(:openstack)
-                      .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Project","Email","Enabled"')
-        provider.class.stubs(:openstack)
-                      .with('user', 'delete', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-        provider.destroy
-        expect(provider.exists?).to be_falsey
+          provider.create
+          expect(provider.exists?).to be_truthy
+        end
       end
 
-    end
-
-    describe '#exists' do
-      context 'when user exists' do
-
-        subject(:response) do
+      describe '#destroy' do
+        it 'destroys a user' do
           provider.class.stubs(:openstack)
-                        .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                        .returns('"ID","Name","Project","Email","Enabled"
-"1cb05cfed7c24279be884ba4f6520262","foo","foo","foo@example.com",True
-')
-          response = provider.exists?
+                        .with('user', 'list', '--quiet', '--format', 'csv', '--long')
+                        .returns('"ID","Name","Project","Email","Enabled"')
+          provider.class.stubs(:openstack)
+                        .with('user', 'delete', [])
+          provider.destroy
+          expect(provider.exists?).to be_falsey
         end
 
-        it { is_expected.to be_truthy }
       end
 
-      context 'when user does not exist' do
+      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
 
-        subject(:response) do
-          provider.class.stubs(:openstack)
-                        .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                        .returns('"ID","Name","Project","Email","Enabled"')
-          response = provider.exists?
+          it { is_expected.to be_falsey }
         end
-
-        it { is_expected.to be_falsey }
       end
-    end
 
-    describe '#instances' do
-      it 'finds every user' do
-        provider.class.stubs(:openstack)
-                      .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Project","Email","Enabled"
+      describe '#instances' 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 = provider.instances
-        expect(instances.count).to eq(1)
+          instances = Puppet::Type::Keystone_user::ProviderOpenstack.instances
+          expect(instances.count).to eq(1)
+        end
       end
-    end
 
-    describe '#tenant' do
-      it 'gets the tenant with default backend' do
-        provider.class.stubs(:openstack)
-                      .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Project","Email","Enabled"
+      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
 ')
-        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', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Project","Email","Enabled"
-"1cb05cfed7c24279be884ba4f6520262","foo","","foo@example.com",True
+          provider.class.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('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Project","User"
-"1cb05cfed7c24279be884ba4f6520262","foo","foo","foo"
+          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
 ')
-        tenant = provider.tenant
-        expect(tenant).to eq('foo')
-      end
-    end
-    describe '#tenant=' do
-      context 'when using default backend' do
-        it 'sets the tenant' do
           provider.class.expects(:openstack)
-                        .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-           provider.class.expects(:openstack)
-                         .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                         .returns('"ID","Name","Project","User"
+                        .with('user role', 'list', '--quiet', '--format', 'csv', ['foo', '--project', 'foo'])
+                        .returns('"ID","Name","Project","User"
 "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo"
 ')
-          provider.tenant=('bar')
+          tenant = provider.tenant
+          expect(tenant).to eq('foo')
         end
       end
-      context 'when using LDAP read-write backend' do
-        it 'sets the tenant when _member_ role exists' do
-          provider.class.expects(:openstack)
-                        .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-           provider.class.expects(:openstack)
-                         .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                         .returns('')
-          provider.class.expects(:openstack)
-                        .with('role', 'show', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                        .returns('name="_member_"')
-          provider.class.expects(:openstack)
-                        .with('role', 'add', [['_member_', '--project', 'bar', '--user', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-          provider.tenant=('bar')
-        end
-        it 'sets the tenant when _member_ role does not exist' do
-          provider.class.expects(:openstack)
-                        .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-           provider.class.expects(:openstack)
-                         .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                         .returns('')
-          provider.class.expects(:openstack)
-                        .with('role', 'show', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                        .raises(Puppet::ExecutionFailure, 'no such role _member_')
-          provider.class.expects(:openstack)
-                        .with('role', 'create', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])                      
-                        .returns('name="_member_"')
-          provider.class.expects(:openstack)
-                        .with('role', 'add', [['_member_', '--project', 'bar', '--user', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-          provider.tenant=('bar')
+
+      describe '#tenant=' do
+        context 'when using default backend' do
+          it 'sets the tenant' 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('"ID","Name","Project","User"
+"9fe2ff9ee4384b1894a90878d3e92bab","_member_","bar","foo"
+')
+            provider.tenant=('bar')
+          end
         end
-      end
-      context 'when using LDAP read-only backend' do
-        it 'sets the tenant when _member_ role exists' do
-          provider.class.expects(:openstack)
-                        .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                        .raises(Puppet::ExecutionFailure, 'You are not authorized to perform the requested action: LDAP user update')
-           provider.class.expects(:openstack)
-                         .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                         .returns('')
-          provider.class.expects(:openstack)
-                        .with('role', 'show', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                        .returns('name="_member_"')
-          provider.class.expects(:openstack)
-                        .with('role', 'add', [['_member_', '--project', 'bar', '--user', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-          provider.tenant=('bar')
+
+        context 'when using LDAP read-write backend' do
+          it 'sets the tenant when _member_ role exists' do
+            provider.class.expects(:openstack)
+                          .with('user', 'set', ['foo', '--project', 'bar'])
+            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.class.expects(:openstack)
+                          .with('role', 'add', ['_member_', '--project', 'bar', '--user', 'foo'])
+            provider.tenant=('bar')
+          end
+          it 'sets the tenant when _member_ role does not exist' do
+            provider.class.expects(:openstack)
+                          .with('user', 'set', ['foo', '--project', 'bar'])
+            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_'])
+                          .raises(Puppet::ExecutionFailure, 'no such role _member_')
+            provider.class.expects(:openstack)
+                          .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_"
+')
+            provider.tenant=('bar')
+          end
         end
-        it 'sets the tenant and gets an unexpected exception message' do
-          provider.class.expects(:openstack)
-                        .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                        .raises(Puppet::ExecutionFailure, 'unknown error message')
-          expect{ provider.tenant=('bar') }.to raise_error(Puppet::ExecutionFailure, /unknown error message/)
+
+# This doesn't make sense, need to clarify what's happening with LDAP mock
+=begin
+        context 'when using LDAP read-only backend' do
+          it 'sets the tenant when _member_ role exists' do
+            provider.class.expects(:openstack)
+                          .with('user', 'set', [['foo', '--project', 'bar']])
+                          .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.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
+            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/)
+          end
         end
+=end
       end
     end
-
   end
 
   describe "#password" do
@@ -211,44 +217,41 @@ username="foo"
         :password     => 'foo',
         :tenant       => 'foo',
         :email        => 'foo@example.com',
-        :auth         => {
-          'username'    => 'test',
-          'password'    => 'abc123',
-          'tenant_name' => 'foo',
-          'auth_url'    => 'https://127.0.0.1:5000/v2.0',
-        }
       }
     end
 
-    it 'checks the password with HTTPS' do
-      httpobj = mock('Net::HTTP')
-      httpobj.stubs(:use_ssl=).with(true)
-      httpobj.stubs(:verify_mode=)
-      Net::HTTP.stubs(:start).returns(httpobj)
-      reqobj = mock('Net::HTTP::Post')
-      reqobj.stubs(:body=)
-      reqobj.stubs(:content_type=)
-      Net::HTTP::Post.stubs(:start).returns(reqobj)
-      respobj = mock('Net::HTTPResponse')
-      respobj.stubs(:code).returns('200')
-      httpobj.stubs(:request).returns(respobj)
-      password = provider.password
-      expect(password).to eq('foo')
+    let(:resource) do
+      Puppet::Type::Keystone_user.new(user_attrs)
     end
-    it 'fails the password check with HTTPS' do
-      httpobj = mock('Net::HTTP')
-      httpobj.stubs(:use_ssl=).with(true)
-      httpobj.stubs(:verify_mode=)
-      Net::HTTP.stubs(:start).returns(httpobj)
-      reqobj = mock('Net::HTTP::Post')
-      reqobj.stubs(:body=)
-      reqobj.stubs(:content_type=)
-      Net::HTTP::Post.stubs(:start).returns(reqobj)
-      respobj = mock('Net::HTTPResponse')
-      respobj.stubs(:code).returns('401')
-      httpobj.stubs(:request).returns(respobj)
-      password = provider.password
-      expect(password).to eq(nil)
+
+    let :provider do
+      provider_class.new(resource)
+    end
+
+    shared_examples 'with auth-url environment variable' do
+      ENV['OS_AUTH_URL'] = 'http://localhost:5000'
+    end
+
+    it_behaves_like 'with auth-url environment variable' do
+      it 'checks the password' do
+        Puppet::Provider::Openstack.stubs(:openstack)
+                      .with('token', 'issue', ['--format', 'value'])
+                      .returns('2015-05-14T04:06:05Z
+e664a386befa4a30878dcef20e79f167
+8dce2ae9ecd34c199d2877bf319a3d06
+ac43ec53d5a74a0b9f51523ae41a29f0
+')
+        password = provider.password
+        expect(password).to eq('foo')
+      end
+
+      it 'fails the password check' do
+        Puppet::Provider::Openstack.stubs(:openstack)
+                      .with('token', 'issue', ['--format', 'value'])
+                      .raises(Puppet::ExecutionFailure, 'HTTP 401 invalid authentication')
+        password = provider.password
+        expect(password).to eq(nil)
+      end
     end
 
     describe 'when updating a user with unmanaged password' do
@@ -262,23 +265,9 @@ username="foo"
           :replace_password => 'False',
           :tenant           => 'foo',
           :email            => 'foo@example.com',
-          :auth             => {
-            'username'      => 'test',
-            'password'      => 'abc123',
-            'tenant_name'   => 'foo',
-            'auth_url'      => 'http://127.0.0.1:5000/v2.0',
-          }
         }
       end
 
-      let(:resource) do
-        Puppet::Type::Keystone_user.new(user_attrs)
-      end
-
-      let :provider do
-        provider_class.new(resource)
-      end
-
       it 'should not try to check password' do
         expect(provider.password).to eq('foo')
       end
index f3c35dcf668cc6f5492fd868af5b899091af8287..2490adc52be37d08f0aa3d78cb3fc55f3692d98e 100644 (file)
@@ -6,89 +6,84 @@ provider_class = Puppet::Type.type(:keystone_user_role).provider(:openstack)
 
 describe provider_class do
 
-  describe 'when updating a user\'s role' do
+  shared_examples 'authenticated with environment variables' do
+    ENV['OS_USERNAME']     = 'test'
+    ENV['OS_PASSWORD']     = 'abc123'
+    ENV['OS_PROJECT_NAME'] = 'test'
+    ENV['OS_AUTH_URL']     = 'http://127.0.0.1:5000'
+  end
 
-    let(:user_role_attrs) do
-      {
-        :name         => 'foo@example.com@foo',
-        :ensure       => 'present',
-        :roles        => ['foo', 'bar'],
-        :auth         => {
-          'username'    => 'test',
-          'password'    => 'abc123',
-          'tenant_name' => 'foo',
-          'auth_url'    => 'http://127.0.0.1:5000/v2.0',
+  describe 'when updating a user\'s role' do
+    it_behaves_like 'authenticated with environment variables' do
+      let(:user_role_attrs) do
+        {
+          :name         => 'foo@foo',
+          :ensure       => 'present',
+          :roles        => ['foo', 'bar'],
         }
-      }
-    end
-
-    let(:resource) do
-      Puppet::Type::Keystone_user_role.new(user_role_attrs)
-    end
+      end
 
-    let(:provider) do
-      provider_class.new(resource)
-    end
+      let(:resource) do
+        Puppet::Type::Keystone_user_role.new(user_role_attrs)
+      end
 
-    before(:each) do
-      provider.class.stubs(:openstack)
-                    .with('user', 'list', '--quiet', '--format', 'csv', [['--project', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                    .returns('"ID","Name"
-"1cb05cfed7c24279be884ba4f6520262","foo@example.com"
-')
-      provider.class.stubs(:openstack)
-                    .with('project', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                    .returns('"ID","Name"
-"1cb05cfed7c24279be884ba4f6520262","foo"
-')
-    end
+      let(:provider) do
+        provider_class.new(resource)
+      end
 
-    describe '#create' do
-      it 'adds all the roles to the user' do
+      before(:each) do
         provider.class.stubs(:openstack)
-                      .with('user role', 'list', '--quiet', '--format', 'csv', [['--project', 'foo', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
+                      .with('user', 'list', '--quiet', '--format', 'csv', ['foo', '--project', 'foo'])
                       .returns('"ID","Name","Project","User"
-"1cb05cfed7c24279be884ba4f6520262","foo","foo","foo@example.com"
-"1cb05cfed7c24279be884ba4f6520263","bar","foo","foo@example.com"
+"1cb05cfed7c24279be884ba4f6520262","foo","foo","foo"
 ')
-        provider.class.stubs(:openstack)
-                      .with('role', 'add', [['foo', '--project', 'foo', '--user', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-        provider.class.stubs(:openstack)
-                      .with('role', 'add', [['bar', '--project', 'foo', '--user', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-        provider.create
-        expect(provider.exists?).to be_truthy
       end
-    end
 
-    describe '#destroy' do
-      it 'removes all the roles from a user' do
-        provider.class.stubs(:openstack)
-                      .with('user role', 'list', '--quiet', '--format', 'csv', [['--project', 'foo', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Project","User"')
-        provider.class.stubs(:openstack)
-                      .with('role', 'remove', [['foo', '--project', 'foo', '--user', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-        provider.class.stubs(:openstack)
-                      .with('role', 'remove', [['bar', '--project', 'foo', '--user', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-        provider.destroy
-        expect(provider.exists?).to be_falsey
+      describe '#create' 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.create
+          expect(provider.exists?).to be_truthy
+        end
       end
 
-    end
+      describe '#destroy' 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.destroy
+          expect(provider.exists?).to be_falsey
+        end
 
-    describe '#exists' do
-      subject(:response) do
-        provider.class.stubs(:openstack)
-                      .with('user role', 'list', '--quiet', '--format', 'csv', [['--project', 'foo', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Project","User"
-"1cb05ed7c24279be884ba4f6520262","foo","foo","foo@example.com"
-"1cb05ed7c24279be884ba4f6520262","bar","foo","foo@example.com"
-')
-        response = provider.exists?
       end
 
-      it { is_expected.to be_truthy }
+      describe '#exists' 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
 
-    end
+        it { is_expected.to be_truthy }
 
+      end
+    end
   end
 end
diff --git a/3rdparty/modules/keystone/spec/unit/provider/openstack_spec.rb b/3rdparty/modules/keystone/spec/unit/provider/openstack_spec.rb
deleted file mode 100644 (file)
index fa431fd..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-# TODO: This should be extracted into openstacklib during the Kilo cycle
-# Load libraries from aviator here to simulate how they live together in a real puppet run
-$LOAD_PATH.push(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'modules', 'aviator', 'lib'))
-require 'puppet'
-require 'spec_helper'
-require 'puppet/provider/openstack'
-
-
-describe Puppet::Provider::Openstack do
-
-  before(:each) do
-    ENV['OS_USERNAME']    = nil
-    ENV['OS_PASSWORD']    = nil
-    ENV['OS_TENANT_NAME'] = nil
-    ENV['OS_AUTH_URL']    = nil
-  end
-
-  let(:type) do
-    Puppet::Type.newtype(:test_resource) do
-      newparam(:name, :namevar => true)
-      newparam(:auth)
-      newparam(:log_file)
-    end
-  end
-
-  shared_examples 'authenticating with environment variables' do
-    it 'makes a successful request' do
-      ENV['OS_USERNAME']    = 'test'
-      ENV['OS_PASSWORD']    = 'abc123'
-      ENV['OS_TENANT_NAME'] = 'test'
-      ENV['OS_AUTH_URL']    = 'http://127.0.0.1:35357/v2.0'
-      if provider.class == Class
-        provider.stubs(:openstack)
-                .with('project', 'list', '--quiet', '--format', 'csv', [[ '--long' ]])
-                .returns('"ID","Name","Description","Enabled"
-"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
-')
-      else
-        provider.class.stubs(:openstack)
-                    .with('project', 'list', '--quiet', '--format', 'csv', [[ '--long' ]])
-                    .returns('"ID","Name","Description","Enabled"
-"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
-')
-      end
-      response = provider.request('project', 'list', nil, nil, '--long' )
-      expect(response.first[:description]).to match /Test tenant/
-    end
-  end
-
-  shared_examples 'it has no credentials' do
-    it 'fails to authenticate' do
-      expect{ provider.request('project', 'list', nil, nil, '--long') }.to raise_error(Puppet::Error::OpenstackAuthInputError, /No credentials provided/)
-    end
-  end
-
-  describe '#request' do
-
-    context 'with valid password credentials in parameters' do
-      let(:resource_attrs) do
-        {
-          :name         => 'stubresource',
-          :auth         => {
-            'username'    => 'test',
-            'password'    => 'abc123',
-            'tenant_name' => 'test',
-            'auth_url'    => 'http://127.0.0.1:5000/v2.0',
-          }
-        }
-      end
-      let(:provider) do
-        Puppet::Provider::Openstack.new(type.new(resource_attrs))
-      end
-
-      it 'makes a successful request' do
-        provider.class.stubs(:openstack)
-                      .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Description","Enabled"
-"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
-')
-        response = provider.request('project', 'list', nil, resource_attrs[:auth], '--long')
-        expect(response.first[:description]).to match /Test tenant/
-      end
-    end
-
-    context 'with valid openrc file in parameters' do
-      mock = "export OS_USERNAME='test'\nexport OS_PASSWORD='abc123'\nexport OS_TENANT_NAME='test'\nexport OS_AUTH_URL='http://127.0.0.1:5000/v2.0'"
-      let(:resource_attrs) do
-        {
-          :name         => 'stubresource',
-          :auth         => {
-            'openrc' => '/root/openrc'
-          }
-        }
-      end
-      let(:provider) do
-        Puppet::Provider::Openstack.new(type.new(resource_attrs))
-      end
-
-      it 'makes a successful request' do
-        File.expects(:open).with('/root/openrc').returns(StringIO.new(mock))
-        provider.class.stubs(:openstack)
-                      .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Description","Enabled"
-"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
-')
-        response = provider.request('project', 'list', nil, resource_attrs[:auth], '--long')
-        expect(response.first[:description]).to match /Test tenant/
-      end
-    end
-
-    context 'with valid service token in parameters' do
-      let(:resource_attrs) do
-        {
-          :name         => 'stubresource',
-          :auth         => {
-            'token' => 'secrettoken',
-            'auth_url'      => 'http://127.0.0.1:5000/v2.0'
-          }
-        }
-      end
-      let(:provider) do
-        Puppet::Provider::Openstack.new(type.new(resource_attrs))
-      end
-
-      it 'makes a successful request' do
-        provider.class.stubs(:openstack)
-                      .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-token', 'secrettoken', '--os-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('"ID","Name","Description","Enabled"
-"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
-')
-        response = provider.request('project', 'list', nil, resource_attrs[:auth], '--long')
-        expect(response.first[:description]).to match /Test tenant/
-      end
-
-      it 'makes a successful show request' do
-        provider.class.stubs(:openstack)
-                      .with('project', 'show', '--format', 'shell', [['test', '--os-token', 'secrettoken', '--os-url', 'http://127.0.0.1:5000/v2.0']])
-                      .returns('ID="1cb05cfed7c24279be884ba4f6520262"
-Name="test"
-Description="Test Tenant"
-Enabled="True"
-')
-        response = provider.request('project', 'show', 'test', resource_attrs[:auth])
-        expect(response[:description]).to match /Test Tenant/
-        expect(response[:id]).to match /1cb05cfed7c24279be884ba4f6520262/
-        expect(response[:name]).to match /test/
-        expect(response[:enabled]).to match /True/
-      end
-
-    end
-
-    context 'with valid password credentials in environment variables' do
-      it_behaves_like 'authenticating with environment variables' do
-        let(:resource_attrs) do
-          {
-            :name => 'stubresource',
-          }
-        end
-        let(:provider) do
-          Puppet::Provider::Openstack.new(type.new(resource_attrs))
-        end
-      end
-    end
-
-    context 'with no valid credentials' do
-      it_behaves_like 'it has no credentials' do
-        let(:resource_attrs) do
-          {
-            :name => 'stubresource',
-          }
-        end
-        let(:provider) do
-          Puppet::Provider::Openstack.new(type.new(resource_attrs))
-        end
-      end
-    end
-
-    context 'it retries on connection errors' do
-      let(:resource_attrs) do
-        {
-          :name         => 'stubresource',
-          :auth         => {
-            'username'    => 'test',
-            'password'    => 'abc123',
-            'tenant_name' => 'test',
-            'auth_url'    => 'http://127.0.0.1:5000/v2.0',
-          }
-        }
-      end
-      let(:provider) do
-        Puppet::Provider::Openstack.new(type.new(resource_attrs))
-      end
-      it 'retries' do
-        provider.class.stubs(:openstack)
-                      .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']])
-                      .raises(Puppet::ExecutionFailure, 'Unable to establish connection')
-                      .then
-                      .returns('')
-        provider.class.expects(:sleep).with(2).returns(nil)
-        provider.request('project', 'list', nil, resource_attrs[:auth], '--long')
-      end
-    end
-  end
-
-
-  describe '::request' do
-
-    context 'with valid password credentials in environment variables' do
-      it_behaves_like 'authenticating with environment variables' do
-        let(:resource_attrs) do
-          {
-            :name => 'stubresource',
-          }
-        end
-        let(:provider) do
-          Puppet::Provider::Openstack.dup
-        end
-      end
-    end
-
-    context 'with no valid credentials' do
-      it_behaves_like 'it has no credentials' do
-        let(:provider) { Puppet::Provider::Openstack.dup }
-      end
-    end
-
-  end
-
-  describe 'parse_csv' do
-    context 'with mixed stderr' do
-      text = "ERROR: Testing\n\"field\",\"test\",1,2,3\n"
-      csv = Puppet::Provider::Openstack.parse_csv(text)
-      it 'should ignore non-CSV text at the beginning of the input' do
-        expect(csv).to be_kind_of(Array)
-        expect(csv[0]).to match_array(['field', 'test', '1', '2', '3'])
-        expect(csv.size).to eq(1)
-      end
-    end
-
-    context 'with \r\n line endings' do
-      text = "ERROR: Testing\r\n\"field\",\"test\",1,2,3\r\n"
-      csv = Puppet::Provider::Openstack.parse_csv(text)
-      it 'ignore the carriage returns' do
-        expect(csv).to be_kind_of(Array)
-        expect(csv[0]).to match_array(['field', 'test', '1', '2', '3'])
-        expect(csv.size).to eq(1)
-      end
-    end
-
-    context 'with embedded newlines' do
-      text = "ERROR: Testing\n\"field\",\"te\nst\",1,2,3\n"
-      csv = Puppet::Provider::Openstack.parse_csv(text)
-      it 'should parse correctly' do
-        expect(csv).to be_kind_of(Array)
-        expect(csv[0]).to match_array(['field', "te\nst", '1', '2', '3'])
-        expect(csv.size).to eq(1)
-      end
-    end
-  end
-
-end
index ddd3355903c78d693c2875b5d5a147b3811c42b7..c3a3fbb9054e37b3962a7d85df0bf98a61b48277 100644 (file)
@@ -5,36 +5,36 @@ package { 'curl': ensure => present }
 # example of how to build a single node
 # keystone instance backed by sqlite
 # with all of the default admin roles
-node keystone_sqlite {
-  class { 'keystone':
+node 'keystone_sqlite' {
+  class { '::keystone':
     verbose      => true,
     debug        => true,
     catalog_type => 'sql',
     admin_token  => 'admin_token',
   }
-  class { 'keystone::roles::admin':
+  class { '::keystone::roles::admin':
     email    => 'example@abc.com',
     password => 'ChangeMe',
   }
-  class { 'keystone::endpoint':
+  class { '::keystone::endpoint':
     public_url => "http://${::fqdn}:5000/",
     admin_url  => "http://${::fqdn}:35357/",
   }
 }
 
 node keystone_mysql {
-  class { 'mysql::server': }
-  class { 'keystone::db::mysql':
+  class { '::mysql::server': }
+  class { '::keystone::db::mysql':
     password => 'keystone',
   }
-  class { 'keystone':
-    verbose        => true,
-    debug          => true,
-    sql_connection => 'mysql://keystone:keystone@127.0.0.1/keystone',
-    catalog_type   => 'sql',
-    admin_token    => 'admin_token',
+  class { '::keystone':
+    verbose             => true,
+    debug               => true,
+    database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone',
+    catalog_type        => 'sql',
+    admin_token         => 'admin_token',
   }
-  class { 'keystone::roles::admin':
+  class { '::keystone::roles::admin':
     email    => 'test@puppetlabs.com',
     password => 'ChangeMe',
   }
@@ -43,21 +43,21 @@ node keystone_mysql {
 
 # keystone with mysql on another node
 node keystone {
-  class { 'keystone':
-    verbose        => true,
-    debug          => true,
-    sql_connection => 'mysql://keystone:password@127.0.0.1/keystone',
-    catalog_type   => 'sql',
-    admin_token    => 'admin_token',
+  class { '::keystone':
+    verbose             => true,
+    debug               => true,
+    database_connection => 'mysql://keystone:password@127.0.0.1/keystone',
+    catalog_type        => 'sql',
+    admin_token         => 'admin_token',
   }
-  class { 'keystone::db::mysql':
+  class { '::keystone::db::mysql':
     password => 'keystone',
   }
-  class { 'keystone::roles::admin':
+  class { '::keystone::roles::admin':
     email    => 'example@abc.com',
     password => 'ChangeMe',
   }
-  class { 'keystone::endpoint':
+  class { '::keystone::endpoint':
     public_url => "http://${::fqdn}:5000/",
     admin_url  => "http://${::fqdn}:35357/",
   }
diff --git a/3rdparty/modules/openstacklib/CHANGELOG.md b/3rdparty/modules/openstacklib/CHANGELOG.md
new file mode 100644 (file)
index 0000000..944eb5d
--- /dev/null
@@ -0,0 +1,19 @@
+##2015-06-17 - 5.1.0
+###Summary
+
+This is a feature and bugfix release in the Juno series.
+
+####Features
+- Adding augeas insertion check
+
+####Bugfixes
+- MySQL: change default MySQL collate to utf8_general_ci
+
+####Maintenance
+- Update .gitreview file for project rename
+- spec: pin rspec-puppet to 1.0.1
+
+##2014-11-25 - 5.0.0
+###Summary
+
+Initial release for Juno.
index fedea5277b0459ac0216705f9678083dc370e495..1fce4aa9f0d9ac43a55c58743cc907c626a9fdd6 100644 (file)
@@ -2,15 +2,24 @@ source 'https://rubygems.org'
 
 group :development, :test do
   gem 'puppetlabs_spec_helper', :require => false
+  gem 'rspec-puppet', '~> 2.1.0', :require => false
+
+  gem 'puppet-lint', '~> 1.1.0'
   gem 'metadata-json-lint'
-  gem 'puppet-lint', '~> 0.3.2'
-  gem 'rspec-puppet', '~> 1.0.1'
-  gem 'rake', '10.1.1'
-  gem 'rspec'
+  gem 'puppet-lint-param-docs'
+  gem 'puppet-lint-absolute_classname-check'
+  gem 'puppet-lint-absolute_template_path'
+  gem 'puppet-lint-trailing_newline-check'
+
+  # Puppet 4.x related lint checks
+  gem 'puppet-lint-unquoted_string-check'
+  gem 'puppet-lint-leading_zero-check'
+  gem 'puppet-lint-variable_contains_upcase'
+  gem 'puppet-lint-numericvariable'
+
+  gem 'beaker-rspec', :require => false
   gem 'mocha'
   gem 'json'
-  gem 'faraday', '0.8.8',       :require => false
-  gem 'vcr',                    :require => false
 end
 
 if puppetversion = ENV['PUPPET_GEM_VERSION']
index 7aaad113c94eef9d3e8eb53a4192f5a433774e4e..88a11a0e7748b08d7c31023da75fe12e97a26806 100644 (file)
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
+Copyright 2012 OpenStack Foundation
 
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+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
 
-   1. Definitions.
+    http://www.apache.org/licenses/LICENSE-2.0
 
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!) The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright 2014 Puppet Labs Inc
-
-   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.
+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.
index 4e9b7aeab4f488bdd53ecd33e2c66892f992ee8f..90fb090d066e4fd49b381fa95fafe84c61951bee 100644 (file)
@@ -11,7 +11,6 @@ openstacklib
 5. [Limitations - OS compatibility, etc.](#limitations)
 6. [Development - Guide for contributing to the module](#development)
 7. [Contributors - Those with commits](#contributors)
-8. [Release Notes - Notes on the most recent updates to the module](#release-notes)
 
 Overview
 --------
@@ -120,6 +119,60 @@ array or string; optional; default to undef
 Privileges given to the database user;
 string or array of strings; optional; default to 'ALL'
 
+#### Defined type: openstacklib::db::postgresql
+
+The db::postgresql resource is a library resource that can be used by nova,
+cinder, ceilometer, etc., to create a postgresql database and a user with
+configurable privileges.
+
+Typically this resource will be declared with a notify parameter to configure
+the sync command to execute when the database resource is changed.
+
+For example, in heat::db::postgresql you might declare:
+
+```
+::openstacklib::db::postgresql { $dbname:
+  password_hash => postgresql_password($user, $password),
+  dbname        => $dbname,
+  user          => $user,
+  notify        => Exec['heat-dbsync'],
+}
+```
+
+Some modules should ensure that the database is created before the service is
+set up. For example, in keystone::db::postgresql you would have:
+
+```
+::openstacklib::db::postgresql { $dbname:
+  password_hash => postgresql_password($user, $password),
+  dbname        => $dbname,
+  user          => $user,
+  notify        => Exec['keystone-manage db_sync'],
+  before        => Service['keystone'],
+}
+```
+
+** Parameters for openstacklib::db::postgresql: **
+
+#####`password_hash`
+Password hash to use for the database user for this service;
+string; required
+
+#####`dbname`
+The name of the database
+string; optional; default to the $title of the resource, i.e. 'nova'
+
+#####`user`
+The database user to create;
+string; optional; default to the $title of the resource, i.e. 'nova'
+
+#####`encoding`
+The encoding use for the database;
+string; optional; default to undef
+
+#####`privileges`
+Privileges given to the database user;
+string or array of strings; optional; default to 'ALL'
 
 #### Defined type: openstacklib::service_validation
 
@@ -228,7 +281,23 @@ configuration and extra functionality through types and providers.
 Limitations
 -----------
 
-* Limitations will be added as they are discovered.
+The python-migrate system package for RHEL 6 and below is out of date and may
+fail to correctly migrate postgresql databases. While this module does not
+handle database migrations, it is common to set up refresh relationships
+between openstacklib::db::postgresql resource and the database sync exec
+resource. Relying on this behavior may cause errors.
+
+Beaker-Rspec
+------------
+
+This module has beaker-rspec tests
+
+To run:
+
+```shell
+bundle install
+bundle exec rspec spec/acceptance
+```
 
 Development
 -----------
@@ -255,17 +324,3 @@ Puppet Module :: OpenStack Version :: OpenStack Codename
 4.0.0         -> 2014.1.0          -> Icehouse
 5.0.0         -> 2014.2.0          -> Juno
 ```
-
-Release Notes
--------------
-
-**5.1.0**
-
-* Update .gitreview file for project rename
-* Adding augeas insertion check
-* MySQL: change default MySQL collate to utf8_general_ci
-* spec: pin rspec-puppet to 1.0.1
-
-**5.0.0**
-
-* This is the initial release of this module.
diff --git a/3rdparty/modules/openstacklib/checksums.json b/3rdparty/modules/openstacklib/checksums.json
deleted file mode 100644 (file)
index c808945..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-{
-  "Gemfile": "2c4e4ae399db74816aafb47dbc3951a5",
-  "LICENSE": "53173ea25085d832ebb1e9d131dc645d",
-  "README.md": "023e14103588e6eb16aee599338f0798",
-  "Rakefile": "a61c67fc9275174b6d502c7a97d58fba",
-  "lib/puppet/parser/functions/os_database_connection.rb": "f50c5c418a4745f67b863351aa421371",
-  "lib/puppet/provider/aviator.rb": "dfec34e1929a1bb260d26b5382d596a2",
-  "lib/puppet/util/aviator.rb": "6a2f5145b59f2011f04b9598db4d66d6",
-  "manifests/db/mysql/host_access.pp": "0d4b41a44213cd2cae0febe63032b74e",
-  "manifests/db/mysql.pp": "4b2ac1ae2ef9c32c2bdcf5330faa2c85",
-  "manifests/messaging/rabbitmq.pp": "4f2a699c774c57aa645ef7300c87eb9c",
-  "manifests/policy/base.pp": "9fcbf53d8442a2e258cbe1260ac6dc6b",
-  "manifests/policy.pp": "843e98d897e3df8d8d70f8017f7b6e6e",
-  "manifests/service_validation.pp": "7b0ed110553298231d947a131e2570f5",
-  "metadata.json": "a1e6434b728214cb8a0f235468260e86",
-  "spec/classes/init_spec.rb": "62493b66358f3c7acf24b0cfe8a98391",
-  "spec/classes/openstacklib_policy_spec.rb": "806f398cc4a8a9cf11c005608879374c",
-  "spec/defines/openstacklib_db_mysql_host_access_spec.rb": "4e498ba905f57bebc98480207f73e253",
-  "spec/defines/openstacklib_db_mysql_spec.rb": "edac2c0018bb0baaf4b55920b39564e6",
-  "spec/defines/openstacklib_messaging_rabbitmq_spec.rb": "7551d7034f07951fff7cd28ca05adf42",
-  "spec/defines/openstacklib_policy_spec.rb": "6fc8d604b44f2c559bcd2222210031b3",
-  "spec/defines/openstacklib_service_validation_spec.rb": "cbb6e09a2c2bca9b04d699e3509b4827",
-  "spec/fixtures/vcr/aviator/request/with_session.yml": "36b855c8d25e2652a711b4d76ab16b20",
-  "spec/fixtures/vcr/aviator/request/without_session.yml": "ab811807ab346574e7cab61bf111be20",
-  "spec/fixtures/vcr/aviator/session/with_password.yml": "4ceea78a734539233b9de4fe60cb856c",
-  "spec/fixtures/vcr/aviator/session/with_token.yml": "ab811807ab346574e7cab61bf111be20",
-  "spec/functions/os_database_connection_spec.rb": "0cfa88f055785516f56672b1f773a461",
-  "spec/spec_helper.rb": "93f9c20dc020eba3bc244c347b8e5d34",
-  "spec/unit/provider/aviator_spec.rb": "2d736d88dbcd3bb2b4960067df71d51f"
-}
\ No newline at end of file
diff --git a/3rdparty/modules/openstacklib/lib/puppet/provider/aviator.rb b/3rdparty/modules/openstacklib/lib/puppet/provider/aviator.rb
deleted file mode 100644 (file)
index 8de1bf2..0000000
+++ /dev/null
@@ -1,297 +0,0 @@
-require 'puppet'
-require 'puppet/feature/aviator'
-require 'puppet/util/inifile'
-
-class Puppet::Provider::Aviator < Puppet::Provider
-
-  def session
-    @session ||= authenticate(resource[:auth], resource[:log_file])
-  end
-
-  def self.session
-    @session ||= authenticate(nil, nil)
-  end
-
-  def request(service, request, &block)
-    self.class.make_request(service, request, session_data, &block)
-  end
-
-  def self.request(service, request, &block)
-    self.make_request(service, request, session_data, &block)
-  end
-
-  # needed for tests
-  def session_data
-    @session_data
-  end
-
-  def self.session_data
-    @session_data
-  end
-
-  def session_data=(data)
-    @session_data=data
-  end
-
-  def self.session_data=(data)
-    @session_data=data
-  end
-
-  private
-
-  # Attempt to find credentials in this order:
-  # 1. username,password,tenant,host set in type parameters
-  # 2. openrc file path set in type parameters
-  # 3. service token and host set in type parameters
-  # 4. username,password,tenant,host set in environment variables
-  # 5. service token and host set in keystone.conf (backwards compatible version)
-  def authenticate(auth_params, log_file)
-    auth_params ||= {}
-    if password_credentials_set?(auth_params)
-      @session = get_authenticated_session(auth_params, log_file)
-
-    elsif openrc_set?(auth_params)
-      credentials = get_credentials_from_openrc(auth_params['openrc'])
-      @session = get_authenticated_session(credentials, log_file)
-
-    elsif service_credentials_set?(auth_params)
-      session_hash = get_unauthenticated_session(auth_params, log_file)
-      @session_data = session_hash[:data]
-      @session = session_hash[:session]
-
-    elsif env_vars_set?
-      credentials = get_credentials_from_env
-      @session = get_authenticated_session(credentials, log_file)
-
-    else  # Last effort: try to get the token from keystone.conf
-      session_hash = self.class.try_auth_with_token(keystone_file, log_file)
-      @session_data = session_hash[:data]
-      @session = session_hash[:session]
-    end
-  end
-
-  def self.authenticate(auth_params, log_file)
-    auth_params = {} unless auth_params
-    if env_vars_set?
-      credentials = get_credentials_from_env
-      @session = get_authenticated_session(credentials, log_file)
-
-    else  # Last effort: try to get the token from keystone.conf
-      session_hash = try_auth_with_token(keystone_file, log_file)
-      @session_data = session_hash[:data]
-      @session = session_hash[:session]
-    end
-  end
-
-
-  def self.try_auth_with_token(conf_file, log_file)
-    service_token = get_admin_token_from_keystone_file(conf_file)
-    auth_url = get_auth_url_from_keystone_file(conf_file)
-    session_hash = {}
-    if service_token
-      credentials = {
-        'service_token' => service_token,
-        'host_uri'      => auth_url,
-      }
-      session_hash = get_unauthenticated_session(credentials, log_file)
-    else  # All authentication efforts failed
-      raise(Puppet::Error, 'No credentials provided.')
-    end
-  end
-
-
-  def self.make_request(service, request, session_data, &block)
-    response = nil
-    if service && service.default_session_data
-      response = service.request(request, :endpoint_type => 'admin') do |params|
-        yield(params) if block
-      end
-    elsif session_data
-      response = service.request(request, :endpoint_type => 'admin',
-                                 :session_data => session_data) do |params|
-        yield(params) if block
-      end
-    else
-      raise(Puppet::Error, 'Cannot make a request with no session data.')
-    end
-    if response.body.hash['error']
-      raise(Puppet::Error, "Error making request: #{response.body.hash['error']['code']} #{response.body.hash['error']['title']}")
-    end
-    response
-  end
-
-
-  def password_credentials_set?(auth_params)
-    auth_params['username'] && auth_params['password'] && auth_params['tenant_name'] && auth_params['host_uri']
-  end
-
-
-  def openrc_set?(auth_params)
-    auth_params['openrc']
-  end
-
-
-  def service_credentials_set?(auth_params)
-    auth_params['service_token'] && auth_params['host_uri']
-  end
-
-
-  def self.env_vars_set?
-    ENV['OS_USERNAME'] && ENV['OS_PASSWORD'] && ENV['OS_TENANT_NAME'] && ENV['OS_AUTH_URL']
-  end
-
-
-  def env_vars_set?
-    self.class.env_vars_set?
-  end
-
-
-  def get_credentials_from_openrc(file)
-    creds = {}
-    begin
-      File.open(file).readlines.delete_if{|l| l=~ /^#/}.each do |line|
-        key, value = line.split('=')
-        key = key.split(' ').last
-        value = value.chomp.gsub(/'/, '')
-        creds[key] = value
-      end
-      return creds
-    rescue Exception => error
-      return {}
-    end
-  end
-
-
-  def self.get_credentials_from_env
-    ENV.to_hash.dup.delete_if { |key, _| ! (key =~ /^OS/) } # Ruby 1.8.7
-  end
-
-  def get_credentials_from_env
-    self.class.get_credentials_from_env
-  end
-
-
-  def self.keystone_file
-    keystone_file = Puppet::Util::IniConfig::File.new
-    keystone_file.read('/etc/keystone/keystone.conf')
-    keystone_file
-  end
-
-  def keystone_file
-    return @keystone_file if @keystone_file
-    @keystone_file = Puppet::Util::IniConfig::File.new
-    @keystone_file.read('/etc/keystone/keystone.conf')
-    @keystone_file
-  end
-
-
-  def self.get_admin_token_from_keystone_file(conf_file)
-    if conf_file and conf_file['DEFAULT'] and conf_file['DEFAULT']['admin_token']
-      return "#{conf_file['DEFAULT']['admin_token'].strip}"
-    else
-      return nil
-    end
-  end
-
-  def get_admin_token_from_keystone_file
-    conf_file = keystone_file
-    self.class.get_admin_token_from_keystone_file(conf_file)
-  end
-
-
-  def self.get_auth_url_from_keystone_file(conf_file)
-    if conf_file
-      if conf_file['DEFAULT']
-        if conf_file['DEFAULT']['admin_endpoint']
-          auth_url = conf_file['DEFAULT']['admin_endpoint'].strip
-          return versioned_endpoint(auth_url)
-        end
-
-        if conf_file['DEFAULT']['admin_port']
-          admin_port = conf_file['DEFAULT']['admin_port'].strip
-        else
-          admin_port = '35357'
-        end
-
-        if conf_file['DEFAULT']['admin_bind_host']
-          host = conf_file['DEFAULT']['admin_bind_host'].strip
-          if host == "0.0.0.0"
-            host = "127.0.0.1"
-          end
-        else
-          host = "127.0.0.1"
-        end
-      end
-
-      if conf_file['ssl'] && conf_file['ssl']['enable'] && conf_file['ssl']['enable'].strip.downcase == 'true'
-        protocol = 'https'
-      else
-        protocol = 'http'
-      end
-    end
-
-    "#{protocol}://#{host}:#{admin_port}/v2.0/"
-  end
-
-  def get_auth_url_from_keystone_file
-    self.class.get_auth_url_from_keystone_file(keystone_file)
-  end
-
-
-  def self.make_configuration(credentials)
-    host_uri = versioned_endpoint(credentials['host_uri'] || credentials['OS_AUTH_URL'], credentials['api_version'])
-    {
-      :provider => 'openstack',
-      :auth_service => {
-        :name        => 'identity',
-        :host_uri    => host_uri,
-        :request     => 'create_token',
-        :validator   => 'list_tenants',
-      },
-      :auth_credentials => {
-        :username    => credentials['username'] || credentials['OS_USERNAME'],
-        :password    => credentials['password'] || credentials['OS_PASSWORD'],
-        :tenant_name => credentials['tenant_name'] || credentials['OS_TENANT_NAME']
-      }
-    }
-  end
-
-
-  def self.get_authenticated_session(credentials, log_file)
-    configuration = make_configuration(credentials)
-    session = ::Aviator::Session.new(:config => configuration, :log_file => log_file)
-    session.authenticate
-    session
-  end
-
-  def get_authenticated_session(credentials, log_file)
-    self.class.get_authenticated_session(credentials, log_file)
-  end
-
-
-  def self.get_unauthenticated_session(credentials, log_file)
-    configuration = {
-      :provider => 'openstack',
-    }
-    session_data = {
-      :base_url      => credentials['host_uri'],
-      :service_token => credentials['service_token']
-    }
-    session = ::Aviator::Session.new(:config => configuration, :log_file => log_file)
-    { :session => session, :data => session_data }
-  end
-
-  def get_unauthenticated_session(credentials, log_file)
-    self.class.get_unauthenticated_session(credentials, log_file)
-  end
-
-
-  def self.versioned_endpoint(endpoint, version = 'v2.0')
-    version = 'v2.0' if version.nil?
-    if endpoint =~ /\/#{version}\/?$/ || endpoint =~ /\/v2.0\/?$/ || endpoint =~ /\/v3\/?$/
-      endpoint
-    else
-      "#{endpoint.chomp('/')}/#{version}"
-    end
-  end
-end
diff --git a/3rdparty/modules/openstacklib/lib/puppet/provider/openstack.rb b/3rdparty/modules/openstacklib/lib/puppet/provider/openstack.rb
new file mode 100644 (file)
index 0000000..155e5b9
--- /dev/null
@@ -0,0 +1,84 @@
+require 'csv'
+require 'puppet'
+
+class Puppet::Error::OpenstackAuthInputError < Puppet::Error
+end
+
+class Puppet::Error::OpenstackUnauthorizedError < Puppet::Error
+end
+
+class Puppet::Provider::Openstack < Puppet::Provider
+
+  initvars # so commands will work
+  commands :openstack => 'openstack'
+
+  # Returns an array of hashes, where the keys are the downcased CSV headers
+  # with underscores instead of spaces
+  def self.request(service, action, properties, credentials=nil)
+    env = credentials ? credentials.to_env : {}
+    Puppet::Util.withenv(env) do
+      rv = nil
+      timeout = 10
+      end_time = Time.now.to_i + timeout
+      loop do
+        begin
+          if(action == 'list')
+            response = openstack(service, action, '--quiet', '--format', 'csv', properties)
+            response = parse_csv(response)
+            keys = response.delete_at(0) # ID,Name,Description,Enabled
+            rv = response.collect do |line|
+              hash = {}
+              keys.each_index do |index|
+                key = keys[index].downcase.gsub(/ /, '_').to_sym
+                hash[key] = line[index]
+              end
+              hash
+            end
+          elsif(action == 'show' || action == 'create')
+            rv = {}
+            # shell output is name="value"\nid="value2"\ndescription="value3" etc.
+            openstack(service, action, '--format', 'shell', properties).split("\n").each do |line|
+              # key is everything before the first "="
+              key, val = line.split("=", 2)
+              next unless val # Ignore warnings
+              # value is everything after the first "=", with leading and trailing double quotes stripped
+              val = val.gsub(/\A"|"\Z/, '')
+              rv[key.downcase.to_sym] = val
+            end
+          else
+            rv = openstack(service, action, properties)
+          end
+          break
+        rescue Puppet::ExecutionFailure => e
+          if e.message =~ /HTTP 401/
+            raise(Puppet::Error::OpenstackUnauthorizedError, 'Could not authenticate.')
+          elsif e.message =~ /Unable to establish connection/
+            current_time = Time.now.to_i
+            if current_time > end_time
+              break
+            else
+              wait = end_time - current_time
+              Puppet::debug("Non-fatal error: \"#{e.message}\"; retrying for #{wait} more seconds.")
+              if wait > timeout - 2 # Only notice the first time
+                notice("#{service} service is unavailable. Will retry for up to #{wait} seconds.")
+              end
+            end
+            sleep(2)
+          else
+            raise e
+          end
+        end
+      end
+      return rv
+    end
+  end
+
+  private
+
+  def self.parse_csv(text)
+    # Ignore warnings - assume legitimate output starts with a double quoted
+    # string.  Errors will be caught and raised prior to this
+    text = text.split("\n").drop_while { |line| line !~ /^\".*\"/ }.join("\n")
+    return CSV.parse(text + "\n")
+  end
+end
diff --git a/3rdparty/modules/openstacklib/lib/puppet/provider/openstack/auth.rb b/3rdparty/modules/openstacklib/lib/puppet/provider/openstack/auth.rb
new file mode 100644 (file)
index 0000000..93a054e
--- /dev/null
@@ -0,0 +1,49 @@
+require 'puppet/provider/openstack/credentials'
+
+module Puppet::Provider::Openstack::Auth
+
+  RCFILENAME = "#{ENV['HOME']}/openrc"
+
+  def get_os_vars_from_env
+    env = {}
+    ENV.each { |k,v| env.merge!(k => v) if k =~ /^OS_/ }
+    return env
+  end
+
+  def get_os_vars_from_rcfile(filename)
+    env = {}
+    if File.exists?(filename)
+      File.open(filename).readlines.delete_if{|l| l=~ /^#|^$/ }.each do |line|
+        key, value = line.split('=')
+        key = key.split(' ').last
+        value = value.chomp.gsub(/'/, '')
+        env.merge!(key => value) if key =~ /OS_/
+      end
+    end
+    return env
+  end
+
+  def rc_filename
+    RCFILENAME
+  end
+
+  def request(service, action, properties=nil)
+    properties ||= []
+    set_credentials(@credentials, get_os_vars_from_env)
+    unless @credentials.set?
+      @credentials.unset
+      set_credentials(@credentials, get_os_vars_from_rcfile(rc_filename))
+    end
+    unless @credentials.set?
+      raise(Puppet::Error::OpenstackAuthInputError, 'Insufficient credentials to authenticate')
+    end
+    super(service, action, properties, @credentials)
+  end
+
+  def set_credentials(creds, env)
+    env.each do |key, val|
+      var = key.sub(/^OS_/,'').downcase
+      creds.set(var, val)
+    end
+  end
+end
diff --git a/3rdparty/modules/openstacklib/lib/puppet/provider/openstack/credentials.rb b/3rdparty/modules/openstacklib/lib/puppet/provider/openstack/credentials.rb
new file mode 100644 (file)
index 0000000..0dec787
--- /dev/null
@@ -0,0 +1,93 @@
+require 'puppet'
+require 'puppet/provider/openstack'
+
+class Puppet::Provider::Openstack::Credentials
+
+  KEYS = [
+    :auth_url, :password, :project_name, :username,
+    :token, :url,
+    :identity_api_version
+  ]
+
+  KEYS.each { |var| attr_accessor var }
+
+  def self.defined?(name)
+    KEYS.include?(name.to_sym)
+  end
+
+  def set(key, val)
+    if self.class.defined?(key.to_sym)
+      self.instance_variable_set("@#{key}".to_sym, val)
+    end
+  end
+
+  def set?
+    return true if user_password_set? || service_token_set?
+  end
+
+  def service_token_set?
+    return true if @token && @url
+  end
+
+  def to_env
+    env = {}
+    self.instance_variables.each do |var|
+      name = var.to_s.sub(/^@/,'OS_').upcase
+      env.merge!(name => self.instance_variable_get(var))
+    end
+    env
+  end
+
+  def user_password_set?
+    return true if @username && @password && @project_name && @auth_url
+  end
+
+  def unset
+    KEYS.each do |key|
+      if key != :identity_api_version &&
+        self.instance_variable_defined?("@#{key}")
+        set(key, '')
+      end
+    end
+  end
+
+  def version
+    self.class.to_s.sub(/.*V/,'').sub('_','.')
+  end
+end
+
+class Puppet::Provider::Openstack::CredentialsV2_0 < Puppet::Provider::Openstack::Credentials
+end
+
+class Puppet::Provider::Openstack::CredentialsV3 < Puppet::Provider::Openstack::Credentials
+
+  KEYS = [
+    :cacert,
+    :cert,
+    :default_domain,
+    :domain_id,
+    :domain_name,
+    :key,
+    :project_domain_id,
+    :project_domain_name,
+    :project_id,
+    :trust_id,
+    :user_domain_id,
+    :user_domain_name,
+    :user_id
+  ]
+
+  KEYS.each { |var| attr_accessor var }
+
+  def self.defined?(name)
+    KEYS.include?(name.to_sym) || super
+  end
+
+  def user_password_set?
+    return true if (@username || @user_id) && @password && (@project_name || @project_id) && @auth_url
+  end
+
+  def initialize
+    set(:identity_api_version, version)
+  end
+end
diff --git a/3rdparty/modules/openstacklib/lib/puppet/util/aviator.rb b/3rdparty/modules/openstacklib/lib/puppet/util/aviator.rb
deleted file mode 100644 (file)
index bc24b02..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-# Add the auth parameter to whatever type is given
-module Puppet::Util::Aviator
-  def self.add_aviator_params(type)
-
-    type.newparam(:auth) do
-
-      desc <<EOT
-Hash of authentication credentials. Credentials can be specified as
-password credentials, e.g.:
-
-auth => {
-  'username'    => 'test',
-  'password'    => 'passw0rd',
-  'tenant_name' => 'test',
-  'host_uri'    => 'http://localhost:35357/v2.0',
-}
-
-or a path to an openrc file containing these credentials, e.g.:
-
-auth => {
-  'openrc' => '/root/openrc',
-}
-
-or a service token and host, e.g.:
-
-auth => {
-  'service_token' => 'ADMIN',
-  'host_uri'    => 'http://localhost:35357/v2.0',
-}
-
-If not present, the provider will first look for environment variables
-for password credentials and then to /etc/keystone/keystone.conf for a
-service token.
-EOT
-
-      validate do |value|
-        raise(Puppet::Error, 'This property must be a hash') unless value.is_a?(Hash)
-      end
-    end
-
-    type.newparam(:log_file) do
-      desc 'Log file. Defaults to no logging.'
-      defaultto('/dev/null')
-    end
-  end
-end
diff --git a/3rdparty/modules/openstacklib/manifests/db/postgresql.pp b/3rdparty/modules/openstacklib/manifests/db/postgresql.pp
new file mode 100644 (file)
index 0000000..febbb44
--- /dev/null
@@ -0,0 +1,46 @@
+# == Definition: openstacklib::db::postgresql
+#
+# This resource configures a postgresql database for an OpenStack service
+#
+# == Parameters:
+#
+#  [*password_hash*]
+#    Password hash to use for the database user for this service;
+#    string; required
+#
+#  [*dbname*]
+#    The name of the database
+#    string; optional; default to the $title of the resource, i.e. 'nova'
+#
+#  [*user*]
+#    The database user to create;
+#    string; optional; default to the $title of the resource, i.e. 'nova'
+#
+#  [*encoding*]
+#    The charset to use for the database;
+#    string; optional; default to undef
+#
+#  [*privileges*]
+#    Privileges given to the database user;
+#    string or array of strings; optional; default to 'ALL'
+
+define openstacklib::db::postgresql (
+  $password_hash,
+  $dbname     = $title,
+  $user       = $title,
+  $encoding   = undef,
+  $privileges = 'ALL',
+){
+
+  if ((($::operatingsystem == 'RedHat' or $::operatingsystem == 'CentOS') and (versioncmp($::operatingsystemmajrelease, '6') <= 0))
+    or ($::operatingsystem == 'Fedora' and (versioncmp($::operatingsystemmajrelease, '14') <= 0))) {
+    warning('The system packages handling the postgresql infrastructure for OpenStack are out of date and should not be relied on for database migrations.')
+  }
+
+  postgresql::server::db { $dbname:
+    user     => $user,
+    password => $password_hash,
+    encoding => $encoding,
+    grant    => $privileges,
+  }
+}
diff --git a/3rdparty/modules/openstacklib/manifests/openstackclient.pp b/3rdparty/modules/openstacklib/manifests/openstackclient.pp
new file mode 100644 (file)
index 0000000..096741c
--- /dev/null
@@ -0,0 +1,18 @@
+# == Class: openstacklib::openstackclient
+#
+# Installs the openstackclient
+#
+# == Parameters
+#
+#  [*package_ensure*]
+#    Ensure state of the openstackclient package.
+#    Optional. Defaults to 'present'.
+#
+class openstacklib::openstackclient(
+  $package_ensure = 'present',
+){
+  package { 'python-openstackclient':
+    ensure => $package_ensure,
+    tag    => 'openstack',
+  }
+}
index 01919fe650e27d1c279411339f3de16d5fca2d77..d5c457a5c67ded19eb14749c1c568d3a49e9073c 100644 (file)
@@ -28,17 +28,17 @@ define openstacklib::policy::base (
     incl    => $file_path,
     changes => [
       "set dict/entry[last()+1] \"${key}\"",
-      "set dict/entry[last()]/string \"${value}\""
+      "set dict/entry[last()]/string \"${value}\"",
     ],
-    onlyif  => "match dict/entry[*][.=\"${key}\"] size == 0"
+    onlyif  => "match dict/entry[*][.=\"${key}\"] size == 0",
   }
 
   # Requires that the entry is added before this call or it will fail.
   augeas { "${file_path}-${key}-${value}" :
     lens    => 'Json.lns',
     incl    => $file_path,
-    changes => "set dict/entry[*][.=\"${key}\"]/string ${value}",
-    require => Augeas["${file_path}-${key}-${value}-add"]
+    changes => "set dict/entry[*][.=\"${key}\"]/string \"${value}\"",
+    require => Augeas["${file_path}-${key}-${value}-add"],
   }
 
 }
diff --git a/3rdparty/modules/openstacklib/manifests/wsgi/apache.pp b/3rdparty/modules/openstacklib/manifests/wsgi/apache.pp
new file mode 100644 (file)
index 0000000..3b497ff
--- /dev/null
@@ -0,0 +1,204 @@
+#
+# Copyright (C) 2014 eNovance SAS <licensing@enovance.com>
+#
+# Author: Emilien Macchi <emilien.macchi@enovance.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# == Class: openstacklib::wsgi::apache
+#
+# Serve a service with apache mod_wsgi
+# When using this class you should disable your service.
+#
+# == Parameters
+#
+# [*service_name*]
+#   (optional) Name of the service to run.
+#   Example: nova-api
+#   Defaults to $name
+#
+# [*servername*]
+#   (optional) The servername for the virtualhost.
+#   Defaults to $::fqdn
+#
+# [*bind_host*]
+#   (optional) The host/ip address Apache will listen on.
+#   Defaults to undef (listen on all ip addresses).
+#
+# [*bind_port*]
+#   (optional) The port to listen.
+#   Defaults to undef
+#
+# [*group*]
+#   (optional) Group with permissions on the script
+#   Defaults to undef
+#
+# [*path*]
+#   (optional) The prefix for the endpoint.
+#   Defaults to '/'
+#
+# [*priority*]
+#   (optional) The priority for the vhost.
+#   Defaults to '10'
+#
+# [*ssl*]
+#   (optional) Use ssl ? (boolean)
+#   Defaults to false
+#
+# [*ssl_cert*]
+#   (optional) Path to SSL certificate
+#   Default to apache::vhost 'ssl_*' defaults.
+#
+# [*ssl_key*]
+#   (optional) Path to SSL key
+#   Default to apache::vhost 'ssl_*' defaults.
+#
+# [*ssl_chain*]
+#   (optional) SSL chain
+#   Default to apache::vhost 'ssl_*' defaults.
+#
+# [*ssl_ca*]
+#   (optional) Path to SSL certificate authority
+#   Default to apache::vhost 'ssl_*' defaults.
+#
+# [*ssl_crl_path*]
+#   (optional) Path to SSL certificate revocation list
+#   Default to apache::vhost 'ssl_*' defaults.
+#
+# [*ssl_crl*]
+#   (optional) SSL certificate revocation list name
+#   Default to apache::vhost 'ssl_*' defaults.
+#
+# [*ssl_certs_dir*]
+#   (optional) Path to SSL certificate directory
+#   Default to apache::vhost 'ssl_*' defaults.
+#
+# [*threads*]
+#   (optional) The number of threads for the vhost.
+#   Defaults to $::processorcount
+#
+# [*user*]
+#   (optional) User with permissions on the script
+#   Defaults to undef
+#
+# [*workers*]
+#   (optional) The number of workers for the vhost.
+#   Defaults to '1'
+#
+# [*wsgi_daemon_process*]
+#   (optional) Name of the WSGI daemon process.
+#   Defaults to $name
+#
+# [*wsgi_process_group*]
+#   (optional) Name of the WSGI process group.
+#   Defaults to $name
+#
+# [*wsgi_script_dir*]
+#   (optional) The directory path of the WSGI script.
+#   Defaults to undef
+#
+# [*wsgi_script_file*]
+#   (optional) The file path of the WSGI script.
+#   Defaults to undef
+#
+# [*wsgi_script_source*]
+#   (optional) The source of the WSGI script.
+#   Defaults to undef
+#
+define openstacklib::wsgi::apache (
+  $service_name        = $name,
+  $bind_host           = undef,
+  $bind_port           = undef,
+  $group               = undef,
+  $path                = '/',
+  $priority            = '10',
+  $servername          = $::fqdn,
+  $ssl                 = false,
+  $ssl_ca              = undef,
+  $ssl_cert            = undef,
+  $ssl_certs_dir       = undef,
+  $ssl_chain           = undef,
+  $ssl_crl             = undef,
+  $ssl_crl_path        = undef,
+  $ssl_key             = undef,
+  $threads             = $::processorcount,
+  $user                = undef,
+  $workers             = 1,
+  $wsgi_daemon_process = $name,
+  $wsgi_process_group  = $name,
+  $wsgi_script_dir     = undef,
+  $wsgi_script_file    = undef,
+  $wsgi_script_source  = undef,
+) {
+
+  include ::apache
+  include ::apache::mod::wsgi
+  if $ssl {
+    include ::apache::mod::ssl
+  }
+
+  # Ensure there's no trailing '/' except if this is also the only character
+  $path_real = regsubst($path, '(^/.*)/$', '\1')
+
+  if !defined(File[$wsgi_script_dir]) {
+    file { $wsgi_script_dir:
+      ensure  => directory,
+      owner   => $user,
+      group   => $group,
+      require => Package['httpd'],
+    }
+  }
+
+  file { $service_name:
+    ensure  => file,
+    path    => "${wsgi_script_dir}/${wsgi_script_file}",
+    source  => $wsgi_script_source,
+    owner   => $user,
+    group   => $group,
+    mode    => '0644',
+    require => File[$wsgi_script_dir],
+  }
+
+  $wsgi_daemon_process_options = {
+    user      => $user,
+    group     => $group,
+    processes => $workers,
+    threads   => $threads,
+  }
+  $wsgi_script_aliases = hash([$path_real,"${wsgi_script_dir}/${wsgi_script_file}"])
+
+  ::apache::vhost { $service_name:
+    ensure                      => 'present',
+    servername                  => $servername,
+    ip                          => $bind_host,
+    port                        => $bind_port,
+    docroot                     => $wsgi_script_dir,
+    docroot_owner               => $user,
+    docroot_group               => $group,
+    priority                    => $priority,
+    ssl                         => $ssl,
+    ssl_cert                    => $ssl_cert,
+    ssl_key                     => $ssl_key,
+    ssl_chain                   => $ssl_chain,
+    ssl_ca                      => $ssl_ca,
+    ssl_crl_path                => $ssl_crl_path,
+    ssl_crl                     => $ssl_crl,
+    ssl_certs_dir               => $ssl_certs_dir,
+    wsgi_daemon_process         => $wsgi_daemon_process,
+    wsgi_daemon_process_options => $wsgi_daemon_process_options,
+    wsgi_process_group          => $wsgi_process_group,
+    wsgi_script_aliases         => $wsgi_script_aliases,
+    require                     => File[$service_name],
+  }
+
+}
index e941bfdf1cbf70c81438f063b23719a83387a56e..3bd6d9ffe0fe6650a1bdd485ed935aa55375747c 100644 (file)
@@ -7,49 +7,34 @@
   "source": "git://github.com/openstack/puppet-openstacklib.git",
   "project_page": "https://launchpad.net/puppet-openstacklib",
   "issues_url": "https://bugs.launchpad.net/puppet-openstacklib",
-  "dependencies": [
-    {"name":"aimonb/aviator","version_requirement":">=0.4.2 <1.0.0"},
-    {"name":"puppetlabs/mysql","version_requirement":">=2.2.0 <3.0.0"},
-    {"name":"puppetlabs/stdlib","version_requirement":">=4.0.0 <5.0.0"},
-    {"name":"puppetlabs/rabbitmq","version_requirement":">=2.0.2 <4.0.0"}
-  ],
   "requirements": [
-    {
-      "name": "pe",
-      "version_requirement": "3.x"
-    },
-    {
-      "name": "puppet",
-      "version_requirement": "3.x"
-    }
+    { "name": "pe","version_requirement": "3.x" },
+    { "name": "puppet","version_requirement": "3.x" }
   ],
   "operatingsystem_support": [
     {
       "operatingsystem": "Debian",
-      "operatingsystemrelease": [
-        "7"
-      ]
+      "operatingsystemrelease": ["7"]
     },
     {
       "operatingsystem": "Fedora",
-      "operatingsystemrelease": [
-        "20"
-      ]
+      "operatingsystemrelease": ["20"]
     },
     {
       "operatingsystem": "RedHat",
-      "operatingsystemrelease": [
-        "6.5",
-        "7"
-      ]
+      "operatingsystemrelease": ["6.5","7"]
     },
     {
       "operatingsystem": "Ubuntu",
-      "operatingsystemrelease": [
-        "12.04",
-        "14.04"
-      ]
+      "operatingsystemrelease": ["12.04","14.04"]
     }
   ],
-  "description": "Puppet module library to expose common functionality between OpenStack modules."
+  "description": "Puppet module library to expose common functionality between OpenStack modules.",
+  "dependencies": [
+    { "name": "puppetlabs/apache", "version_requirement": ">=1.0.0 <2.0.0" },
+    { "name": "puppetlabs/mysql", "version_requirement": ">=3.0.0 <4.0.0" },
+    { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" },
+    { "name": "puppetlabs/rabbitmq", "version_requirement": ">=2.0.2 <4.0.0" },
+    { "name": "puppetlabs/postgresql", "version_requirement": ">=3.3.0 <4.0.0" }
+  ]
 }
diff --git a/3rdparty/modules/openstacklib/spec/acceptance/mysql_spec.rb b/3rdparty/modules/openstacklib/spec/acceptance/mysql_spec.rb
new file mode 100644 (file)
index 0000000..0088971
--- /dev/null
@@ -0,0 +1,35 @@
+require 'spec_helper_acceptance'
+
+describe 'openstacklib mysql' do
+
+  context 'default parameters' do
+
+    it 'should work with no errors' do
+      pp= <<-EOS
+      Exec { logoutput => 'on_failure' }
+
+      class { '::mysql::server': }
+
+      ::openstacklib::db::mysql { 'beaker':
+        password_hash => mysql_password('keystone'),
+        allowed_hosts => '127.0.0.1',
+      }
+      EOS
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe port(3306) do
+      it { is_expected.to be_listening.with('tcp') }
+    end
+
+    describe 'test database listing' do
+      it 'should list beaker database' do
+        expect(shell("mysql -e 'show databases;'|grep -q beaker").exit_code).to be_zero
+      end
+    end
+
+  end
+end
diff --git a/3rdparty/modules/openstacklib/spec/acceptance/nodesets/default.yml b/3rdparty/modules/openstacklib/spec/acceptance/nodesets/default.yml
new file mode 100644 (file)
index 0000000..a2c1ecc
--- /dev/null
@@ -0,0 +1,9 @@
+HOSTS:
+  ubuntu-14.04-amd64:
+    roles:
+      - master
+    platform: ubuntu-14.04-amd64
+    hypervisor : none
+    ip: 127.0.0.1
+CONFIG:
+  type: foss
diff --git a/3rdparty/modules/openstacklib/spec/acceptance/nodesets/nodepool-centos7.yml b/3rdparty/modules/openstacklib/spec/acceptance/nodesets/nodepool-centos7.yml
new file mode 100644 (file)
index 0000000..575ae67
--- /dev/null
@@ -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/3rdparty/modules/openstacklib/spec/acceptance/nodesets/nodepool-trusty.yml b/3rdparty/modules/openstacklib/spec/acceptance/nodesets/nodepool-trusty.yml
new file mode 100644 (file)
index 0000000..a95d9f3
--- /dev/null
@@ -0,0 +1,10 @@
+HOSTS:
+  ubuntu-14.04-amd64:
+    roles:
+      - master
+    platform: ubuntu-14.04-amd64
+    hypervisor : none
+    ip: 127.0.0.1
+CONFIG:
+  type: foss
+  set_env: false
diff --git a/3rdparty/modules/openstacklib/spec/acceptance/rabbitmq_spec.rb b/3rdparty/modules/openstacklib/spec/acceptance/rabbitmq_spec.rb
new file mode 100644 (file)
index 0000000..51e8e99
--- /dev/null
@@ -0,0 +1,65 @@
+require 'spec_helper_acceptance'
+
+describe 'openstacklib class' do
+
+  context 'default parameters' do
+
+    it 'should work with no errors' do
+      pp= <<-EOS
+      Exec { logoutput => 'on_failure' }
+
+      if $::osfamily == 'RedHat' {
+        # RabbitMQ is not available in default repo
+        class { '::openstack_extras::repo::redhat::redhat':
+          # Kilo is not GA yet, so let's use the testing repo
+          manage_rdo => false,
+          repo_hash  => {
+            'rdo-kilo-testing' => {
+              'baseurl'  => 'https://repos.fedorapeople.org/repos/openstack/openstack-kilo/testing/el7/',
+              # packages are not GA so not signed
+              'gpgcheck' => '0',
+              'priority' => 97,
+            },
+          },
+        }
+        $package_provider = 'yum'
+      } else {
+        $package_provider = 'apt'
+      }
+
+      class { '::rabbitmq':
+        delete_guest_user => true,
+        package_provider  => $package_provider
+      }
+
+      # openstacklib resources
+      include ::openstacklib::openstackclient
+
+      ::openstacklib::messaging::rabbitmq { 'beaker':
+        userid   => 'beaker',
+        is_admin => true,
+      }
+      EOS
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe 'test rabbitmq resources' do
+      it 'should list rabbitmq beaker resources' do
+        shell('rabbitmqctl list_users') do |r|
+          expect(r.stdout).to match(/^beaker/)
+          expect(r.stdout).not_to match(/^guest/)
+          expect(r.exit_code).to eq(0)
+        end
+
+        shell('rabbitmqctl list_permissions') do |r|
+          expect(r.stdout).to match(/^beaker\t\.\*\t\.\*\t\.\*$/)
+          expect(r.exit_code).to eq(0)
+        end
+      end
+    end
+
+  end
+end
index 9d6927c52666fc9a165ed2931c3c750d1934abfd..9c11441e01e209dbfe05c548024ab54327af50a2 100644 (file)
@@ -15,7 +15,7 @@ describe 'openstacklib::policy' do
   end
 
   it 'configures the proper policy' do
-    should contain_openstacklib__policy__base('foo').with(
+    is_expected.to contain_openstacklib__policy__base('foo').with(
       :file_path => '/etc/nova/policy.json',
       :key       => 'context_is_admin',
       :value     => 'foo:bar'
index 8f47bfa136ea50370ba111153e6871dd837004de..d3e1d30d8b6a1183ea76f46449ab3750d81d59c1 100644 (file)
@@ -19,11 +19,11 @@ describe 'openstacklib::db::mysql::host_access' do
           :privileges    => 'ALL' }
       end
 
-      it { should contain_mysql_user("#{params[:user]}@10.0.0.1").with(
+      it { is_expected.to contain_mysql_user("#{params[:user]}@10.0.0.1").with(
         :password_hash => params[:password_hash]
       )}
 
-      it { should contain_mysql_grant("#{params[:user]}@10.0.0.1/#{params[:database]}.*").with(
+      it { is_expected.to contain_mysql_grant("#{params[:user]}@10.0.0.1/#{params[:database]}.*").with(
         :user       => "#{params[:user]}@10.0.0.1",
         :privileges => 'ALL',
         :table      => "#{params[:database]}.*"
index fc9b54ec3b2ac10224e54f3e7fee50c8326d2df2..ca6884a33b09c8eec175a03008f07fb9f60b0bfd 100644 (file)
@@ -19,11 +19,11 @@ describe 'openstacklib::db::mysql' do
         required_params
       end
 
-      it { should contain_mysql_database(title).with(
+      it { is_expected.to contain_mysql_database(title).with(
         :charset => 'utf8',
         :collate => 'utf8_general_ci'
       )}
-      it { should contain_openstacklib__db__mysql__host_access("#{title}_127.0.0.1").with(
+      it { is_expected.to contain_openstacklib__db__mysql__host_access("#{title}_127.0.0.1").with(
         :user       => title,
         :database   => title,
         :privileges => 'ALL'
@@ -35,11 +35,11 @@ describe 'openstacklib::db::mysql' do
         { :dbname => 'foobar' }.merge(required_params)
       end
 
-      it { should contain_mysql_database(params[:dbname]).with(
+      it { is_expected.to contain_mysql_database(params[:dbname]).with(
         :charset => 'utf8',
         :collate => 'utf8_general_ci'
       )}
-      it { should contain_openstacklib__db__mysql__host_access("#{params[:dbname]}_127.0.0.1").with(
+      it { is_expected.to contain_openstacklib__db__mysql__host_access("#{params[:dbname]}_127.0.0.1").with(
         :user       => title,
         :database   => params[:dbname],
         :privileges => 'ALL'
@@ -51,11 +51,11 @@ describe 'openstacklib::db::mysql' do
         { :user => 'foobar' }.merge(required_params)
       end
 
-      it { should contain_mysql_database(title).with(
+      it { is_expected.to contain_mysql_database(title).with(
         :charset => 'utf8',
         :collate => 'utf8_general_ci'
       )}
-      it { should contain_openstacklib__db__mysql__host_access("#{title}_127.0.0.1").with(
+      it { is_expected.to contain_openstacklib__db__mysql__host_access("#{title}_127.0.0.1").with(
         :user       => params[:user],
         :database   => title,
         :privileges => 'ALL',
@@ -67,14 +67,14 @@ describe 'openstacklib::db::mysql' do
         { :charset => 'latin1' }.merge(required_params)
       end
 
-      it { should contain_mysql_database(title).with_charset(params[:charset]) }
+      it { is_expected.to contain_mysql_database(title).with_charset(params[:charset]) }
     end
 
     context 'when omitting the required parameter password_hash' do
       let :params do
         required_params.delete(:password_hash)
       end
-      it { expect { should raise_error(Puppet::Error) } }
+      it { expect { is_expected.to raise_error(Puppet::Error) } }
     end
 
     context 'when notifying other resources' do
@@ -85,7 +85,7 @@ describe 'openstacklib::db::mysql' do
         { :notify => 'Exec[nova-db-sync]'}.merge(required_params)
       end
 
-      it { should contain_exec('nova-db-sync').that_subscribes_to("Openstacklib::Db::Mysql[#{title}]") }
+      it { is_expected.to contain_exec('nova-db-sync').that_subscribes_to("Openstacklib::Db::Mysql[#{title}]") }
     end
 
     context 'when required for other openstack services' do
@@ -99,7 +99,7 @@ describe 'openstacklib::db::mysql' do
         { :before => 'Service[keystone]'}.merge(required_params)
       end
 
-      it { should contain_service('keystone').that_requires("Openstacklib::Db::Mysql[keystone]") }
+      it { is_expected.to contain_service('keystone').that_requires("Openstacklib::Db::Mysql[keystone]") }
     end
 
     context "overriding allowed_hosts parameter with array value" do
@@ -107,12 +107,12 @@ describe 'openstacklib::db::mysql' do
         { :allowed_hosts  => ['127.0.0.1','%'] }.merge(required_params)
       end
 
-      it {should contain_openstacklib__db__mysql__host_access("#{title}_127.0.0.1").with(
+      it {is_expected.to contain_openstacklib__db__mysql__host_access("#{title}_127.0.0.1").with(
         :user          => title,
         :password_hash => params[:password_hash],
         :database      => title
       )}
-      it {should contain_openstacklib__db__mysql__host_access("#{title}_%").with(
+      it {is_expected.to contain_openstacklib__db__mysql__host_access("#{title}_%").with(
         :user          => title,
         :password_hash => params[:password_hash],
         :database      => title
@@ -124,7 +124,7 @@ describe 'openstacklib::db::mysql' do
         { :allowed_hosts => '192.168.1.1' }.merge(required_params)
       end
 
-      it {should contain_openstacklib__db__mysql__host_access("#{title}_192.168.1.1").with(
+      it {is_expected.to contain_openstacklib__db__mysql__host_access("#{title}_192.168.1.1").with(
         :user          => title,
         :password_hash => params[:password_hash],
         :database      => title
@@ -136,7 +136,7 @@ describe 'openstacklib::db::mysql' do
         { :allowed_hosts => '127.0.0.1' }.merge(required_params)
       end
 
-      it {should contain_openstacklib__db__mysql__host_access("#{title}_127.0.0.1").with(
+      it {is_expected.to contain_openstacklib__db__mysql__host_access("#{title}_127.0.0.1").with(
         :user          => title,
         :password_hash => params[:password_hash],
         :database      => title
diff --git a/3rdparty/modules/openstacklib/spec/defines/openstacklib_db_postgresql_spec.rb b/3rdparty/modules/openstacklib/spec/defines/openstacklib_db_postgresql_spec.rb
new file mode 100644 (file)
index 0000000..4e2dfc7
--- /dev/null
@@ -0,0 +1,133 @@
+require 'spec_helper'
+
+describe 'openstacklib::db::postgresql' do
+  password_hash = 'AA1420F182E88B9E5F874F6FBE7459291E8F4601'
+  title = 'nova'
+  let (:title) { title }
+
+  let :required_params do
+    { :password_hash => password_hash }
+  end
+
+  context 'on a RedHat osfamily' do
+    let :facts do
+      {
+        :postgres_default_version => '8.4',
+        :osfamily => 'RedHat'
+      }
+    end
+
+    context 'with only required parameters' do
+      let :params do
+        required_params
+      end
+
+      it { is_expected.to contain_postgresql__server__db(title).with(
+        :user     => title,
+        :password => password_hash
+      )}
+    end
+
+    context 'when overriding encoding' do
+      let :params do
+        { :encoding => 'latin1' }.merge(required_params)
+      end
+      it { is_expected.to contain_postgresql__server__db(title).with_encoding(params[:encoding]) }
+    end
+
+    context 'when omitting the required parameter password_hash' do
+      let :params do
+        required_params.delete(:password_hash)
+      end
+
+      it { expect { is_expected.to raise_error(Puppet::Error) } }
+    end
+
+    context 'when notifying other resources' do
+      let :pre_condition do
+        'exec { "nova-db-sync": }'
+      end
+      let :params do
+        { :notify => 'Exec[nova-db-sync]'}.merge(required_params)
+      end
+
+      it {is_expected.to contain_exec('nova-db-sync').that_subscribes_to("Openstacklib::Db::Postgresql[#{title}]") }
+    end
+
+    context 'when required for other openstack services' do
+      let :pre_condition do
+        'service {"keystone":}'
+      end
+      let :title do
+        'keystone'
+      end
+      let :params do
+        { :before => 'Service[keystone]'}.merge(required_params)
+      end
+
+      it { is_expected.to contain_service('keystone').that_requires("Openstacklib::Db::Postgresql[keystone]") }
+    end
+
+  end
+
+  context 'on a Debian osfamily' do
+    let :facts do
+      {
+        :osfamily => 'Debian'
+      }
+    end
+
+    context 'with only required parameters' do
+      let :params do
+        required_params
+      end
+
+      it { is_expected.to contain_postgresql__server__db(title).with(
+        :user     => title,
+        :password => password_hash
+      )}
+    end
+
+    context 'when overriding encoding' do
+      let :params do
+        { :encoding => 'latin1' }.merge(required_params)
+      end
+      it { is_expected.to contain_postgresql__server__db(title).with_encoding(params[:encoding]) }
+    end
+
+    context 'when omitting the required parameter password_hash' do
+      let :params do
+        required_params.delete(:password_hash)
+      end
+
+      it { expect { is_expected.to raise_error(Puppet::Error) } }
+    end
+
+    context 'when notifying other resources' do
+      let :pre_condition do
+        'exec { "nova-db-sync": }'
+      end
+      let :params do
+        { :notify => 'Exec[nova-db-sync]'}.merge(required_params)
+      end
+
+      it {is_expected.to contain_exec('nova-db-sync').that_subscribes_to("Openstacklib::Db::Postgresql[#{title}]") }
+    end
+
+    context 'when required for other openstack services' do
+      let :pre_condition do
+        'service {"keystone":}'
+      end
+      let :title do
+        'keystone'
+      end
+      let :params do
+        { :before => 'Service[keystone]'}.merge(required_params)
+      end
+
+      it { is_expected.to contain_service('keystone').that_requires("Openstacklib::Db::Postgresql[keystone]") }
+    end
+
+  end
+
+end
index 953c53be3c6e885830a94bceb827052c3b66cebc..47e6c41c361545864876c807ca7117ac4599dbc9 100644 (file)
@@ -28,18 +28,18 @@ describe 'openstacklib::messaging::rabbitmq' do
     end
 
     context 'with default parameters' do
-      it { should contain_rabbitmq_user('guest').with(
+      it { is_expected.to contain_rabbitmq_user('guest').with(
         :admin    => false,
         :password => 'guest',
         :provider => 'rabbitmqctl',
       )}
-      it { should contain_rabbitmq_user_permissions('guest@/').with(
+      it { is_expected.to contain_rabbitmq_user_permissions('guest@/').with(
         :configure_permission => '.*',
         :write_permission     => '.*',
         :read_permission      => '.*',
         :provider             => 'rabbitmqctl',
       )}
-      it { should contain_rabbitmq_vhost('/').with(
+      it { is_expected.to contain_rabbitmq_vhost('/').with(
         :provider => 'rabbitmqctl',
       )}
     end
@@ -57,18 +57,18 @@ describe 'openstacklib::messaging::rabbitmq' do
         )
       end
 
-      it { should contain_rabbitmq_user('nova').with(
+      it { is_expected.to contain_rabbitmq_user('nova').with(
         :admin    => true,
         :password => 'secrete',
         :provider => 'rabbitmqctl',
       )}
-      it { should contain_rabbitmq_user_permissions('nova@/nova').with(
+      it { is_expected.to contain_rabbitmq_user_permissions('nova@/nova').with(
         :configure_permission => '.nova',
         :write_permission     => '.nova',
         :read_permission      => '.nova',
         :provider             => 'rabbitmqctl',
       )}
-      it { should contain_rabbitmq_vhost('/nova').with(
+      it { is_expected.to contain_rabbitmq_vhost('/nova').with(
         :provider => 'rabbitmqctl',
       )}
     end
@@ -78,7 +78,7 @@ describe 'openstacklib::messaging::rabbitmq' do
         params.merge!( :manage_vhost => false )
       end
 
-      it { should_not contain_rabbitmq_vhost }
+      it { is_expected.not_to contain_rabbitmq_vhost }
     end
 
   end
index 89be58c798478789fa091091f276f8883f118cb6..6e0bb913147e2125a20161e48556340ea1e30d40 100644 (file)
@@ -8,28 +8,28 @@ describe 'openstacklib::policy::base' do
 
   let :params do
     {:file_path => '/etc/nova/policy.json',
-    :key       => 'context_is_admin',
+    :key       => 'context_is_admin or owner',
     :value     => 'foo:bar'}
   end
 
-  it 'configures the proper policy' do
-    should contain_augeas('/etc/nova/policy.json-context_is_admin-foo:bar').with(
+  it 'configures (modifies) the proper policy' do
+    is_expected.to contain_augeas('/etc/nova/policy.json-context_is_admin or owner-foo:bar').with(
       'lens'    => 'Json.lns',
       'incl'    => '/etc/nova/policy.json',
-      'changes' => 'set dict/entry[*][.="context_is_admin"]/string foo:bar',
-      'require' => 'Augeas[/etc/nova/policy.json-context_is_admin-foo:bar-add]'
+      'changes' => 'set dict/entry[*][.="context_is_admin or owner"]/string "foo:bar"',
+      'require' => 'Augeas[/etc/nova/policy.json-context_is_admin or owner-foo:bar-add]'
     )
   end
 
-  it 'configures the proper policy' do
-    should contain_augeas('/etc/nova/policy.json-context_is_admin-foo:bar-add').with(
+  it 'configures (adds) the proper policy' do
+    is_expected.to contain_augeas('/etc/nova/policy.json-context_is_admin or owner-foo:bar-add').with(
       'lens'    => 'Json.lns',
       'incl'    => '/etc/nova/policy.json',
       'changes' => [
-          'set dict/entry[last()+1] "context_is_admin"',
+          'set dict/entry[last()+1] "context_is_admin or owner"',
           'set dict/entry[last()]/string "foo:bar"'
       ],
-      'onlyif' => 'match dict/entry[*][.="context_is_admin"] size == 0'
+      'onlyif' => 'match dict/entry[*][.="context_is_admin or owner"] size == 0'
     )
   end
 
index 17e4389a69afd46ca36f39cc2e7ed49c706902ff..cc196f076a5807546a9b1dd5c3fc8aa4f0d9af77 100644 (file)
@@ -32,7 +32,7 @@ describe 'openstacklib::service_validation' do
         required_params
       end
 
-      it { should contain_exec("execute #{title} validation").with(
+      it { is_expected.to contain_exec("execute #{title} validation").with(
         :path      => '/usr/bin:/bin:/usr/sbin:/sbin',
         :provider  => 'shell',
         :command   => 'nova list',
@@ -40,7 +40,7 @@ describe 'openstacklib::service_validation' do
         :try_sleep => '2',
       )}
 
-      it { should contain_anchor("create #{title} anchor").with(
+      it { is_expected.to contain_anchor("create #{title} anchor").with(
         :require => "Exec[execute #{title} validation]",
       )}
 
@@ -50,7 +50,7 @@ describe 'openstacklib::service_validation' do
       let :params do
         required_params.delete(:command)
       end
-      it { expect { should raise_error(Puppet::Error) } }
+      it { expect { is_expected.to raise_error(Puppet::Error) } }
     end
 
   end
diff --git a/3rdparty/modules/openstacklib/spec/defines/openstacklib_wsgi_apache_spec.rb b/3rdparty/modules/openstacklib/spec/defines/openstacklib_wsgi_apache_spec.rb
new file mode 100644 (file)
index 0000000..15bd3f0
--- /dev/null
@@ -0,0 +1,127 @@
+#
+# Copyright (C) 2014 eNovance SAS <licensing@enovance.com>
+#
+# Author: Emilien Macchi <emilien.macchi@enovance.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+require 'spec_helper'
+
+describe 'openstacklib::wsgi::apache' do
+
+  let (:title) { 'keystone_wsgi' }
+
+  let :global_facts do
+    {
+      :processorcount => 42,
+      :concat_basedir => '/var/lib/puppet/concat',
+      :fqdn           => 'some.host.tld'
+    }
+  end
+
+  let :params do
+    {
+      :bind_port          => 5000,
+      :group              => 'keystone',
+      :ssl                => true,
+      :user               => 'keystone',
+      :wsgi_script_dir    => '/var/www/cgi-bin/keystone',
+      :wsgi_script_file   => 'main',
+      :wsgi_script_source => '/usr/share/keystone/keystone.wsgi'
+    }
+  end
+
+  shared_examples_for 'apache serving a service with mod_wsgi' do
+    it { is_expected.to contain_service('httpd').with_name(platform_parameters[:httpd_service_name]) }
+    it { is_expected.to contain_class('apache') }
+    it { is_expected.to contain_class('apache::mod::wsgi') }
+
+    describe 'with default parameters' do
+
+      it { is_expected.to contain_file('/var/www/cgi-bin/keystone').with(
+        'ensure'  => 'directory',
+        'owner'   => 'keystone',
+        'group'   => 'keystone',
+        'require' => 'Package[httpd]'
+      )}
+
+      it { is_expected.to contain_file('keystone_wsgi').with(
+        'ensure'  => 'file',
+        'path'    => '/var/www/cgi-bin/keystone/main',
+        'source'  => '/usr/share/keystone/keystone.wsgi',
+        'owner'   => 'keystone',
+        'group'   => 'keystone',
+        'mode'    => '0644',
+      )}
+
+      it { is_expected.to contain_apache__vhost('keystone_wsgi').with(
+        'servername'                  => 'some.host.tld',
+        'ip'                          => nil,
+        'port'                        => '5000',
+        'docroot'                     => '/var/www/cgi-bin/keystone',
+        'docroot_owner'               => 'keystone',
+        'docroot_group'               => 'keystone',
+        'ssl'                         => 'true',
+        'wsgi_daemon_process'         => 'keystone_wsgi',
+        'wsgi_process_group'          => 'keystone_wsgi',
+        'wsgi_script_aliases'         => { '/' => "/var/www/cgi-bin/keystone/main" },
+        'wsgi_daemon_process_options' => {
+          'user'      => 'keystone',
+          'group'     => 'keystone',
+          'processes' => 1,
+          'threads'   => global_facts[:processorcount],
+        },
+        'require'                     => 'File[keystone_wsgi]'
+      )}
+      it { is_expected.to contain_file("#{platform_parameters[:httpd_ports_file]}") }
+    end
+
+  end
+
+  context 'on RedHat platforms' do
+    let :facts do
+      global_facts.merge({
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '7.0'
+      })
+    end
+
+    let :platform_parameters do
+      {
+        :httpd_service_name => 'httpd',
+        :httpd_ports_file   => '/etc/httpd/conf/ports.conf',
+      }
+    end
+
+    it_configures 'apache serving a service with mod_wsgi'
+  end
+
+  context 'on Debian platforms' do
+    let :facts do
+      global_facts.merge({
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Debian',
+        :operatingsystemrelease => '7.0'
+      })
+    end
+
+    let :platform_parameters do
+      {
+        :httpd_service_name => 'apache2',
+        :httpd_ports_file   => '/etc/apache2/ports.conf',
+      }
+    end
+
+    it_configures 'apache serving a service with mod_wsgi'
+  end
+end
diff --git a/3rdparty/modules/openstacklib/spec/fixtures/vcr/aviator/request/with_session.yml b/3rdparty/modules/openstacklib/spec/fixtures/vcr/aviator/request/with_session.yml
deleted file mode 100644 (file)
index 2d052df..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
---- 
-  http_interactions: 
-    - request: 
-        method: post
-        uri: "http://192.168.11.4:35357/v2.0/tokens"
-        body: 
-          encoding: UTF-8
-          string: "{\x22auth\x22:{\x22passwordCredentials\x22:{\x22username\x22:\x22admin\x22,\x22password\x22:\x22fyby-tet\x22},\x22tenantName\x22:\x22admin\x22}}"
-        headers: 
-          Content-Type: 
-            - application/json
-          User-Agent: 
-            - "Faraday v0.8.8"
-      response: 
-        status: 
-          code: 200
-          message: 
-        headers: 
-          vary: 
-            - X-Auth-Token
-          content-type: 
-            - application/json
-          content-length: 
-            - "9780"
-          date: 
-            - "Tue, 30 Sep 2014 06:59:48 GMT"
-          connection: 
-            - close
-        body: 
-          encoding: UTF-8
-          string: "{\x22access\x22: {\x22token\x22: {\x22issued_at\x22: \x222014-09-30T06:59:48.338940\x22, \x22expires\x22: \x222014-09-30T07:59:48Z\x22, \x22id\x22: \x22MIIRIAYJKoZIhvcNAQcCoIIRETCCEQ0CAQExCTAHBgUrDgMCGjCCD3YGCSqGSIb3DQEHAaCCD2cEgg9jeyJhY2Nlc3MiOiB7InRva2VuIjogeyJpc3N1ZWRfYXQiOiAiMjAxNC0wOS0zMFQwNjo1OTo0OC4zMzg5NDAiLCAiZXhwaXJlcyI6ICIyMDE0LTA5LTMwVDA3OjU5OjQ4WiIsICJpZCI6ICJwbGFjZWhvbGRlciIsICJ0ZW5hbnQiOiB7ImRlc2NyaXB0aW9uIjogImFkbWluIHRlbmFudCIsICJlbmFibGVkIjogdHJ1ZSwgImlkIjogImM1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgIm5hbWUiOiAiYWRtaW4ifX0sICJzZXJ2aWNlQ2F0YWxvZyI6IFt7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc0L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMWJiNzU4NWIzMzgxNGI4Mjk4NzJlYjQ0MjAyMTg5OGEiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NC92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJjb21wdXRlIiwgIm5hbWUiOiAibm92YSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJpZCI6ICJhYTdkNDU2NTNhYjI0ZGY2YmE5ZDE4NGE1ZWRkNGYxMyIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo5Njk2LyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJuZXR3b3JrIiwgIm5hbWUiOiAibmV1dHJvbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMmJmNGQ5YzZiYTgwNDM1M2JjZGNlZGZjNTAxMDNiYjYiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWV2MiIsICJuYW1lIjogImNpbmRlcnYyIn0sIHsiZW5kcG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjMiLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3NC92MyIsICJpZCI6ICIzZmQ4NDBjYmFkZDM0NmFiOTE2YjA2YWYxZjRlNWJmMCIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo4Nzc0L3YzIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImNvbXB1dGV2MyIsICJuYW1lIjogIm5vdmF2MyJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5MjkyIiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40OjkyOTIiLCAiaWQiOiAiMTJjOTM1NzkwYmM5NGE3ODljNzJmOWJiYjIxZjM5YmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6OTI5MiJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJpbWFnZSIsICJuYW1lIjogImdsYW5jZSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc3IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzciLCAiaWQiOiAiMWNlNDkwMWQ4OTE1NDIzZTk2ZGFiM2ZlMWZiMzY2M2MiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJtZXRlcmluZyIsICJuYW1lIjogImNlaWxvbWV0ZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAiaWQiOiAiNWU4ZjExYzk3ZTgwNDNiNWJkZTA1YmVhMmRlNDYxNmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODAwMC92MS8ifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiY2xvdWRmb3JtYXRpb24iLCAibmFtZSI6ICJoZWF0LWNmbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiNTRiOWVjMjhiYzYwNDI1MmIwMGNmZTZlMGU0NGFhOTQiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWUiLCAibmFtZSI6ICJjaW5kZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3My9zZXJ2aWNlcy9BZG1pbiIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4NzczL3NlcnZpY2VzL0Nsb3VkIiwgImlkIjogIjA3NWVjNzliMGJlMzQxYmFhYmUyZTliMTIwNTkxZjQ4IiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40Ojg3NzMvc2VydmljZXMvQ2xvdWQifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiZWMyIiwgIm5hbWUiOiAibm92YV9lYzIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwNC92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4MDA0L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgImlkIjogIjI2MmM0YjM3MzY3ODQ2OGE5ODU1YTNlYmM2MDE1OTYwIiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40OjgwMDQvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAib3JjaGVzdHJhdGlvbiIsICJuYW1lIjogImhlYXQifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6MzUzNTcvdjIuMCIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo1MDAwL3YyLjAiLCAiaWQiOiAiMDg5ZmRiMjIyNDk1NDZiOTlhMWU1N2FlYzBiMWU3NmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6NTAwMC92Mi4wIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImlkZW50aXR5IiwgIm5hbWUiOiAia2V5c3RvbmUifV0sICJ1c2VyIjogeyJ1c2VybmFtZSI6ICJhZG1pbiIsICJyb2xlc19saW5rcyI6IFtdLCAiaWQiOiAiM2Y3NmI5NDY2NzQzNGNmM2JkYzMyM2NmMDIxYzUwZjgiLCAicm9sZXMiOiBbeyJuYW1lIjogImFkbWluIn1dLCAibmFtZSI6ICJhZG1pbiJ9LCAibWV0YWRhdGEiOiB7ImlzX2FkbWluIjogMCwgInJvbGVzIjogWyIxZThiYzVkMWYzYTQ0OGU5YTJhMWNkYTU4ZDk3ZjkyYiJdfX19MYIBgTCCAX0CAQEwXDBXMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVW5zZXQxDjAMBgNVBAcMBVVuc2V0MQ4wDAYDVQQKDAVVbnNldDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tAgEBMAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIBAHGQ0NFb0OcE74KIU9DmmvgVyYCrNwwWrwG1CObr9111AHfEr+bn6YfX1ePRUhB2KpcuBPLeIfM-RlLHNwpLzYtvKIwdj0TxIecbF9PuTkWMEZ9Kxl+KE8F4dJOnv0XnAiWZ8QzrMZOo4d+owLJmNNLE1TKfGqv8ughdcrjHtUicHT2E0AOfO3ylEhJPsazUl8XIIWQ4sMWTrs0ROMiZnWPWbomYb49LIaREHD6nDfZX+EDZbHSfPVLTYVL-+qkiIH52-lXqz-OKPCn+Lt3RzXYDzapZd8cpzVgJpTuq2YKMZ+H06yvHFCTZNN49j6kZHz0Qkn2MjbwU8sH10wA7W6k=\x22, \x22tenant\x22: {\x22description\x22: \x22admin tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c518b36fa220499b85ba9a71014ce2a5\x22, \x22name\x22: \x22admin\x22}}, \x22serviceCatalog\x22: [{\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8774/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8774/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x221bb7585b33814b829872eb442021898a\x22, \x22publicURL\x22: \x22http://192.168.11.4:8774/v2/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22compute\x22, \x22name\x22: \x22nova\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:9696/\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:9696/\x22, \x22id\x22: \x22aa7d45653ab24df6ba9d184a5edd4f13\x22, \x22publicURL\x22: \x22http://192.168.11.4:9696/\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22network\x22, \x22name\x22: \x22neutron\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8776/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8776/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x222bf4d9c6ba804353bcdcedfc50103bb6\x22, \x22publicURL\x22: \x22http://192.168.11.4:8776/v2/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22volumev2\x22, \x22name\x22: \x22cinderv2\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8774/v3\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8774/v3\x22, \x22id\x22: \x223fd840cbadd346ab916b06af1f4e5bf0\x22, \x22publicURL\x22: \x22http://192.168.11.4:8774/v3\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22computev3\x22, \x22name\x22: \x22novav3\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:9292\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:9292\x22, \x22id\x22: \x2212c935790bc94a789c72f9bbb21f39bc\x22, \x22publicURL\x22: \x22http://192.168.11.4:9292\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22image\x22, \x22name\x22: \x22glance\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8777\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8777\x22, \x22id\x22: \x221ce4901d8915423e96dab3fe1fb3663c\x22, \x22publicURL\x22: \x22http://192.168.11.4:8777\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22metering\x22, \x22name\x22: \x22ceilometer\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8000/v1/\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8000/v1/\x22, \x22id\x22: \x225e8f11c97e8043b5bde05bea2de4616c\x22, \x22publicURL\x22: \x22http://192.168.11.4:8000/v1/\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22cloudformation\x22, \x22name\x22: \x22heat-cfn\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8776/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8776/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x2254b9ec28bc604252b00cfe6e0e44aa94\x22, \x22publicURL\x22: \x22http://192.168.11.4:8776/v1/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22volume\x22, \x22name\x22: \x22cinder\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8773/services/Admin\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8773/services/Cloud\x22, \x22id\x22: \x22075ec79b0be341baabe2e9b120591f48\x22, \x22publicURL\x22: \x22http://192.168.11.4:8773/services/Cloud\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22ec2\x22, \x22name\x22: \x22nova_ec2\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8004/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8004/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x22262c4b373678468a9855a3ebc6015960\x22, \x22publicURL\x22: \x22http://192.168.11.4:8004/v1/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22orchestration\x22, \x22name\x22: \x22heat\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:35357/v2.0\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:5000/v2.0\x22, \x22id\x22: \x22089fdb22249546b99a1e57aec0b1e76c\x22, \x22publicURL\x22: \x22http://192.168.11.4:5000/v2.0\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22identity\x22, \x22name\x22: \x22keystone\x22}], \x22user\x22: {\x22username\x22: \x22admin\x22, \x22roles_links\x22: [], \x22id\x22: \x223f76b94667434cf3bdc323cf021c50f8\x22, \x22roles\x22: [{\x22name\x22: \x22admin\x22}], \x22name\x22: \x22admin\x22}, \x22metadata\x22: {\x22is_admin\x22: 0, \x22roles\x22: [\x221e8bc5d1f3a448e9a2a1cda58d97f92b\x22]}}}"
-        http_version: 
-      recorded_at: "Tue, 30 Sep 2014 06:59:48 GMT"
-    - request: 
-        method: get
-        uri: "http://172.16.33.4:35357/v2.0/tenants"
-        body: 
-          encoding: US-ASCII
-          string: ""
-        headers: 
-          Content-Type: 
-            - application/json
-          User-Agent: 
-            - "Faraday v0.8.8"
-          X-Auth-Token: 
-            - "MIIRIAYJKoZIhvcNAQcCoIIRETCCEQ0CAQExCTAHBgUrDgMCGjCCD3YGCSqGSIb3DQEHAaCCD2cEgg9jeyJhY2Nlc3MiOiB7InRva2VuIjogeyJpc3N1ZWRfYXQiOiAiMjAxNC0wOS0zMFQwNjo1OTo0OC4zMzg5NDAiLCAiZXhwaXJlcyI6ICIyMDE0LTA5LTMwVDA3OjU5OjQ4WiIsICJpZCI6ICJwbGFjZWhvbGRlciIsICJ0ZW5hbnQiOiB7ImRlc2NyaXB0aW9uIjogImFkbWluIHRlbmFudCIsICJlbmFibGVkIjogdHJ1ZSwgImlkIjogImM1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgIm5hbWUiOiAiYWRtaW4ifX0sICJzZXJ2aWNlQ2F0YWxvZyI6IFt7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc0L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMWJiNzU4NWIzMzgxNGI4Mjk4NzJlYjQ0MjAyMTg5OGEiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NC92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJjb21wdXRlIiwgIm5hbWUiOiAibm92YSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJpZCI6ICJhYTdkNDU2NTNhYjI0ZGY2YmE5ZDE4NGE1ZWRkNGYxMyIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo5Njk2LyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJuZXR3b3JrIiwgIm5hbWUiOiAibmV1dHJvbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMmJmNGQ5YzZiYTgwNDM1M2JjZGNlZGZjNTAxMDNiYjYiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWV2MiIsICJuYW1lIjogImNpbmRlcnYyIn0sIHsiZW5kcG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjMiLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3NC92MyIsICJpZCI6ICIzZmQ4NDBjYmFkZDM0NmFiOTE2YjA2YWYxZjRlNWJmMCIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo4Nzc0L3YzIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImNvbXB1dGV2MyIsICJuYW1lIjogIm5vdmF2MyJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5MjkyIiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40OjkyOTIiLCAiaWQiOiAiMTJjOTM1NzkwYmM5NGE3ODljNzJmOWJiYjIxZjM5YmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6OTI5MiJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJpbWFnZSIsICJuYW1lIjogImdsYW5jZSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc3IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzciLCAiaWQiOiAiMWNlNDkwMWQ4OTE1NDIzZTk2ZGFiM2ZlMWZiMzY2M2MiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJtZXRlcmluZyIsICJuYW1lIjogImNlaWxvbWV0ZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAiaWQiOiAiNWU4ZjExYzk3ZTgwNDNiNWJkZTA1YmVhMmRlNDYxNmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODAwMC92MS8ifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiY2xvdWRmb3JtYXRpb24iLCAibmFtZSI6ICJoZWF0LWNmbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiNTRiOWVjMjhiYzYwNDI1MmIwMGNmZTZlMGU0NGFhOTQiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWUiLCAibmFtZSI6ICJjaW5kZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3My9zZXJ2aWNlcy9BZG1pbiIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4NzczL3NlcnZpY2VzL0Nsb3VkIiwgImlkIjogIjA3NWVjNzliMGJlMzQxYmFhYmUyZTliMTIwNTkxZjQ4IiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40Ojg3NzMvc2VydmljZXMvQ2xvdWQifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiZWMyIiwgIm5hbWUiOiAibm92YV9lYzIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwNC92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4MDA0L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgImlkIjogIjI2MmM0YjM3MzY3ODQ2OGE5ODU1YTNlYmM2MDE1OTYwIiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40OjgwMDQvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAib3JjaGVzdHJhdGlvbiIsICJuYW1lIjogImhlYXQifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6MzUzNTcvdjIuMCIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo1MDAwL3YyLjAiLCAiaWQiOiAiMDg5ZmRiMjIyNDk1NDZiOTlhMWU1N2FlYzBiMWU3NmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6NTAwMC92Mi4wIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImlkZW50aXR5IiwgIm5hbWUiOiAia2V5c3RvbmUifV0sICJ1c2VyIjogeyJ1c2VybmFtZSI6ICJhZG1pbiIsICJyb2xlc19saW5rcyI6IFtdLCAiaWQiOiAiM2Y3NmI5NDY2NzQzNGNmM2JkYzMyM2NmMDIxYzUwZjgiLCAicm9sZXMiOiBbeyJuYW1lIjogImFkbWluIn1dLCAibmFtZSI6ICJhZG1pbiJ9LCAibWV0YWRhdGEiOiB7ImlzX2FkbWluIjogMCwgInJvbGVzIjogWyIxZThiYzVkMWYzYTQ0OGU5YTJhMWNkYTU4ZDk3ZjkyYiJdfX19MYIBgTCCAX0CAQEwXDBXMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVW5zZXQxDjAMBgNVBAcMBVVuc2V0MQ4wDAYDVQQKDAVVbnNldDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tAgEBMAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIBAHGQ0NFb0OcE74KIU9DmmvgVyYCrNwwWrwG1CObr9111AHfEr+bn6YfX1ePRUhB2KpcuBPLeIfM-RlLHNwpLzYtvKIwdj0TxIecbF9PuTkWMEZ9Kxl+KE8F4dJOnv0XnAiWZ8QzrMZOo4d+owLJmNNLE1TKfGqv8ughdcrjHtUicHT2E0AOfO3ylEhJPsazUl8XIIWQ4sMWTrs0ROMiZnWPWbomYb49LIaREHD6nDfZX+EDZbHSfPVLTYVL-+qkiIH52-lXqz-OKPCn+Lt3RzXYDzapZd8cpzVgJpTuq2YKMZ+H06yvHFCTZNN49j6kZHz0Qkn2MjbwU8sH10wA7W6k="
-      response: 
-        status: 
-          code: 200
-          message: 
-        headers: 
-          vary: 
-            - X-Auth-Token
-          content-type: 
-            - application/json
-          content-length: 
-            - "491"
-          date: 
-            - "Tue, 30 Sep 2014 06:59:48 GMT"
-          connection: 
-            - close
-        body: 
-          encoding: UTF-8
-          string: "{\x22tenants_links\x22: [], \x22tenants\x22: [{\x22description\x22: \x22Test tenant\x22, \x22enabled\x22: true, \x22id\x22: \x2234e463e2bab24f78990ca864e4a28ba2\x22, \x22name\x22: \x22test2\x22}, {\x22description\x22: \x22Tenant for the openstack services\x22, \x22enabled\x22: true, \x22id\x22: \x2268c8fcf77aff4b409cc158c0f6cbff7b\x22, \x22name\x22: \x22services\x22}, {\x22description\x22: \x22Test tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c330f1bc663648df9c1e7835a1e7a955\x22, \x22name\x22: \x22test\x22}, {\x22description\x22: \x22admin tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c518b36fa220499b85ba9a71014ce2a5\x22, \x22name\x22: \x22admin\x22}]}"
-        http_version: 
-      recorded_at: "Tue, 30 Sep 2014 06:59:48 GMT"
-  recorded_with: "VCR 2.9.3"
\ No newline at end of file
diff --git a/3rdparty/modules/openstacklib/spec/fixtures/vcr/aviator/request/without_session.yml b/3rdparty/modules/openstacklib/spec/fixtures/vcr/aviator/request/without_session.yml
deleted file mode 100644 (file)
index 784fb2f..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
---- 
-  http_interactions: 
-    - request: 
-        method: get
-        uri: "http://192.168.11.4:35357/v2.0/tenants"
-        body: 
-          encoding: US-ASCII
-          string: ""
-        headers: 
-          Content-Type: 
-            - application/json
-          User-Agent: 
-            - "Faraday v0.8.8"
-          X-Auth-Token: 
-            - sosp-kyl
-      response: 
-        status: 
-          code: 200
-          message: 
-        headers: 
-          vary: 
-            - X-Auth-Token
-          content-type: 
-            - application/json
-          content-length: 
-            - "491"
-          date: 
-            - "Tue, 30 Sep 2014 06:59:48 GMT"
-          connection: 
-            - close
-        body: 
-          encoding: UTF-8
-          string: "{\x22tenants_links\x22: [], \x22tenants\x22: [{\x22description\x22: \x22Test tenant\x22, \x22enabled\x22: true, \x22id\x22: \x2234e463e2bab24f78990ca864e4a28ba2\x22, \x22name\x22: \x22test2\x22}, {\x22description\x22: \x22Tenant for the openstack services\x22, \x22enabled\x22: true, \x22id\x22: \x2268c8fcf77aff4b409cc158c0f6cbff7b\x22, \x22name\x22: \x22services\x22}, {\x22description\x22: \x22Test tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c330f1bc663648df9c1e7835a1e7a955\x22, \x22name\x22: \x22test\x22}, {\x22description\x22: \x22admin tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c518b36fa220499b85ba9a71014ce2a5\x22, \x22name\x22: \x22admin\x22}]}"
-        http_version: 
-      recorded_at: "Tue, 30 Sep 2014 06:59:48 GMT"
-  recorded_with: "VCR 2.9.3"
\ No newline at end of file
diff --git a/3rdparty/modules/openstacklib/spec/fixtures/vcr/aviator/session/with_password.yml b/3rdparty/modules/openstacklib/spec/fixtures/vcr/aviator/session/with_password.yml
deleted file mode 100644 (file)
index 3faa474..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
---- 
-  http_interactions: 
-    - request: 
-        method: post
-        uri: "http://192.168.11.4:35357/v2.0/tokens"
-        body: 
-          encoding: UTF-8
-          string: "{\x22auth\x22:{\x22passwordCredentials\x22:{\x22username\x22:\x22admin\x22,\x22password\x22:\x22fyby-tet\x22},\x22tenantName\x22:\x22admin\x22}}"
-        headers: 
-          Content-Type: 
-            - application/json
-          User-Agent: 
-            - "Faraday v0.8.8"
-      response: 
-        status: 
-          code: 200
-          message: 
-        headers: 
-          vary: 
-            - X-Auth-Token
-          content-type: 
-            - application/json
-          content-length: 
-            - "9780"
-          date: 
-            - "Tue, 30 Sep 2014 07:16:15 GMT"
-          connection: 
-            - close
-        body: 
-          encoding: UTF-8
-          string: "{\x22access\x22: {\x22token\x22: {\x22issued_at\x22: \x222014-09-30T07:16:15.042778\x22, \x22expires\x22: \x222014-09-30T08:16:15Z\x22, \x22id\x22: \x22MIIRIAYJKoZIhvcNAQcCoIIRETCCEQ0CAQExCTAHBgUrDgMCGjCCD3YGCSqGSIb3DQEHAaCCD2cEgg9jeyJhY2Nlc3MiOiB7InRva2VuIjogeyJpc3N1ZWRfYXQiOiAiMjAxNC0wOS0zMFQwNzoxNjoxNS4wNDI3NzgiLCAiZXhwaXJlcyI6ICIyMDE0LTA5LTMwVDA4OjE2OjE1WiIsICJpZCI6ICJwbGFjZWhvbGRlciIsICJ0ZW5hbnQiOiB7ImRlc2NyaXB0aW9uIjogImFkbWluIHRlbmFudCIsICJlbmFibGVkIjogdHJ1ZSwgImlkIjogImM1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgIm5hbWUiOiAiYWRtaW4ifX0sICJzZXJ2aWNlQ2F0YWxvZyI6IFt7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc0L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMWJiNzU4NWIzMzgxNGI4Mjk4NzJlYjQ0MjAyMTg5OGEiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NC92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJjb21wdXRlIiwgIm5hbWUiOiAibm92YSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJpZCI6ICJhYTdkNDU2NTNhYjI0ZGY2YmE5ZDE4NGE1ZWRkNGYxMyIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo5Njk2LyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJuZXR3b3JrIiwgIm5hbWUiOiAibmV1dHJvbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMmJmNGQ5YzZiYTgwNDM1M2JjZGNlZGZjNTAxMDNiYjYiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWV2MiIsICJuYW1lIjogImNpbmRlcnYyIn0sIHsiZW5kcG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjMiLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3NC92MyIsICJpZCI6ICIzZmQ4NDBjYmFkZDM0NmFiOTE2YjA2YWYxZjRlNWJmMCIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo4Nzc0L3YzIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImNvbXB1dGV2MyIsICJuYW1lIjogIm5vdmF2MyJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5MjkyIiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40OjkyOTIiLCAiaWQiOiAiMTJjOTM1NzkwYmM5NGE3ODljNzJmOWJiYjIxZjM5YmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6OTI5MiJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJpbWFnZSIsICJuYW1lIjogImdsYW5jZSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc3IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzciLCAiaWQiOiAiMWNlNDkwMWQ4OTE1NDIzZTk2ZGFiM2ZlMWZiMzY2M2MiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJtZXRlcmluZyIsICJuYW1lIjogImNlaWxvbWV0ZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAiaWQiOiAiNWU4ZjExYzk3ZTgwNDNiNWJkZTA1YmVhMmRlNDYxNmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODAwMC92MS8ifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiY2xvdWRmb3JtYXRpb24iLCAibmFtZSI6ICJoZWF0LWNmbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiNTRiOWVjMjhiYzYwNDI1MmIwMGNmZTZlMGU0NGFhOTQiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWUiLCAibmFtZSI6ICJjaW5kZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3My9zZXJ2aWNlcy9BZG1pbiIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4NzczL3NlcnZpY2VzL0Nsb3VkIiwgImlkIjogIjA3NWVjNzliMGJlMzQxYmFhYmUyZTliMTIwNTkxZjQ4IiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40Ojg3NzMvc2VydmljZXMvQ2xvdWQifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiZWMyIiwgIm5hbWUiOiAibm92YV9lYzIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwNC92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4MDA0L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgImlkIjogIjI2MmM0YjM3MzY3ODQ2OGE5ODU1YTNlYmM2MDE1OTYwIiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40OjgwMDQvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAib3JjaGVzdHJhdGlvbiIsICJuYW1lIjogImhlYXQifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6MzUzNTcvdjIuMCIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo1MDAwL3YyLjAiLCAiaWQiOiAiMDg5ZmRiMjIyNDk1NDZiOTlhMWU1N2FlYzBiMWU3NmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6NTAwMC92Mi4wIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImlkZW50aXR5IiwgIm5hbWUiOiAia2V5c3RvbmUifV0sICJ1c2VyIjogeyJ1c2VybmFtZSI6ICJhZG1pbiIsICJyb2xlc19saW5rcyI6IFtdLCAiaWQiOiAiM2Y3NmI5NDY2NzQzNGNmM2JkYzMyM2NmMDIxYzUwZjgiLCAicm9sZXMiOiBbeyJuYW1lIjogImFkbWluIn1dLCAibmFtZSI6ICJhZG1pbiJ9LCAibWV0YWRhdGEiOiB7ImlzX2FkbWluIjogMCwgInJvbGVzIjogWyIxZThiYzVkMWYzYTQ0OGU5YTJhMWNkYTU4ZDk3ZjkyYiJdfX19MYIBgTCCAX0CAQEwXDBXMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVW5zZXQxDjAMBgNVBAcMBVVuc2V0MQ4wDAYDVQQKDAVVbnNldDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tAgEBMAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIBAEOAl3MRmSUB+J+kRi+qRhwOrNRmj-wDqT5nJTlbafOjofSXsHG683LaipA7oPoH-ARUPDxXIZfevRue7bQQB3I4cWIUSItIPyW4xDpF+iHy3QOm+I-3v3ctze2Z3Rp0TRaYFsItTZZETsSXI28yBt9+3Dsk3a7Vv10HAZetbV1i6qu6avLcJsmN-1J3KLwCDSEvpMgDAcpzAnhba1fi+X8GrCCTz4c1uIcPfsHxX4g8gNkB4-VT0lkRmfSxdrGeRz0uN12oDqgCL64IV1mJ6Bi9Unh15QFcLwU0F8ote+joG9G29fw3WDzneXHIeEIZSBXmOAX2kQBOnZa2sZg8gls=\x22, \x22tenant\x22: {\x22description\x22: \x22admin tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c518b36fa220499b85ba9a71014ce2a5\x22, \x22name\x22: \x22admin\x22}}, \x22serviceCatalog\x22: [{\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8774/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8774/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x221bb7585b33814b829872eb442021898a\x22, \x22publicURL\x22: \x22http://192.168.11.4:8774/v2/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22compute\x22, \x22name\x22: \x22nova\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:9696/\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:9696/\x22, \x22id\x22: \x22aa7d45653ab24df6ba9d184a5edd4f13\x22, \x22publicURL\x22: \x22http://192.168.11.4:9696/\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22network\x22, \x22name\x22: \x22neutron\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8776/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8776/v2/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x222bf4d9c6ba804353bcdcedfc50103bb6\x22, \x22publicURL\x22: \x22http://192.168.11.4:8776/v2/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22volumev2\x22, \x22name\x22: \x22cinderv2\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8774/v3\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8774/v3\x22, \x22id\x22: \x223fd840cbadd346ab916b06af1f4e5bf0\x22, \x22publicURL\x22: \x22http://192.168.11.4:8774/v3\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22computev3\x22, \x22name\x22: \x22novav3\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:9292\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:9292\x22, \x22id\x22: \x2212c935790bc94a789c72f9bbb21f39bc\x22, \x22publicURL\x22: \x22http://192.168.11.4:9292\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22image\x22, \x22name\x22: \x22glance\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8777\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8777\x22, \x22id\x22: \x221ce4901d8915423e96dab3fe1fb3663c\x22, \x22publicURL\x22: \x22http://192.168.11.4:8777\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22metering\x22, \x22name\x22: \x22ceilometer\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8000/v1/\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8000/v1/\x22, \x22id\x22: \x225e8f11c97e8043b5bde05bea2de4616c\x22, \x22publicURL\x22: \x22http://192.168.11.4:8000/v1/\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22cloudformation\x22, \x22name\x22: \x22heat-cfn\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8776/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8776/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x2254b9ec28bc604252b00cfe6e0e44aa94\x22, \x22publicURL\x22: \x22http://192.168.11.4:8776/v1/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22volume\x22, \x22name\x22: \x22cinder\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8773/services/Admin\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8773/services/Cloud\x22, \x22id\x22: \x22075ec79b0be341baabe2e9b120591f48\x22, \x22publicURL\x22: \x22http://192.168.11.4:8773/services/Cloud\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22ec2\x22, \x22name\x22: \x22nova_ec2\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:8004/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:8004/v1/c518b36fa220499b85ba9a71014ce2a5\x22, \x22id\x22: \x22262c4b373678468a9855a3ebc6015960\x22, \x22publicURL\x22: \x22http://192.168.11.4:8004/v1/c518b36fa220499b85ba9a71014ce2a5\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22orchestration\x22, \x22name\x22: \x22heat\x22}, {\x22endpoints\x22: [{\x22adminURL\x22: \x22http://172.16.33.4:35357/v2.0\x22, \x22region\x22: \x22openstack\x22, \x22internalURL\x22: \x22http://172.16.33.4:5000/v2.0\x22, \x22id\x22: \x22089fdb22249546b99a1e57aec0b1e76c\x22, \x22publicURL\x22: \x22http://192.168.11.4:5000/v2.0\x22}], \x22endpoints_links\x22: [], \x22type\x22: \x22identity\x22, \x22name\x22: \x22keystone\x22}], \x22user\x22: {\x22username\x22: \x22admin\x22, \x22roles_links\x22: [], \x22id\x22: \x223f76b94667434cf3bdc323cf021c50f8\x22, \x22roles\x22: [{\x22name\x22: \x22admin\x22}], \x22name\x22: \x22admin\x22}, \x22metadata\x22: {\x22is_admin\x22: 0, \x22roles\x22: [\x221e8bc5d1f3a448e9a2a1cda58d97f92b\x22]}}}"
-        http_version: 
-      recorded_at: "Tue, 30 Sep 2014 07:16:15 GMT"
-    - request: 
-        method: get
-        uri: "http://192.168.11.4:5000/v2.0/tenants"
-        body: 
-          encoding: US-ASCII
-          string: ""
-        headers: 
-          Content-Type: 
-            - application/json
-          User-Agent: 
-            - "Faraday v0.8.8"
-          X-Auth-Token: 
-            - "MIIRIAYJKoZIhvcNAQcCoIIRETCCEQ0CAQExCTAHBgUrDgMCGjCCD3YGCSqGSIb3DQEHAaCCD2cEgg9jeyJhY2Nlc3MiOiB7InRva2VuIjogeyJpc3N1ZWRfYXQiOiAiMjAxNC0wOS0zMFQwNzoxNjoxNS4wNDI3NzgiLCAiZXhwaXJlcyI6ICIyMDE0LTA5LTMwVDA4OjE2OjE1WiIsICJpZCI6ICJwbGFjZWhvbGRlciIsICJ0ZW5hbnQiOiB7ImRlc2NyaXB0aW9uIjogImFkbWluIHRlbmFudCIsICJlbmFibGVkIjogdHJ1ZSwgImlkIjogImM1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgIm5hbWUiOiAiYWRtaW4ifX0sICJzZXJ2aWNlQ2F0YWxvZyI6IFt7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc0L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMWJiNzU4NWIzMzgxNGI4Mjk4NzJlYjQ0MjAyMTg5OGEiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NC92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJjb21wdXRlIiwgIm5hbWUiOiAibm92YSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5Njk2LyIsICJpZCI6ICJhYTdkNDU2NTNhYjI0ZGY2YmE5ZDE4NGE1ZWRkNGYxMyIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo5Njk2LyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJuZXR3b3JrIiwgIm5hbWUiOiAibmV1dHJvbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YyL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjIvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiMmJmNGQ5YzZiYTgwNDM1M2JjZGNlZGZjNTAxMDNiYjYiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92Mi9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWV2MiIsICJuYW1lIjogImNpbmRlcnYyIn0sIHsiZW5kcG9pbnRzIjogW3siYWRtaW5VUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzQvdjMiLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3NC92MyIsICJpZCI6ICIzZmQ4NDBjYmFkZDM0NmFiOTE2YjA2YWYxZjRlNWJmMCIsICJwdWJsaWNVUkwiOiAiaHR0cDovLzE5Mi4xNjguMTEuNDo4Nzc0L3YzIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImNvbXB1dGV2MyIsICJuYW1lIjogIm5vdmF2MyJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo5MjkyIiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40OjkyOTIiLCAiaWQiOiAiMTJjOTM1NzkwYmM5NGE3ODljNzJmOWJiYjIxZjM5YmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6OTI5MiJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJpbWFnZSIsICJuYW1lIjogImdsYW5jZSJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc3IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzciLCAiaWQiOiAiMWNlNDkwMWQ4OTE1NDIzZTk2ZGFiM2ZlMWZiMzY2M2MiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3NyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJtZXRlcmluZyIsICJuYW1lIjogImNlaWxvbWV0ZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAicmVnaW9uIjogIm9wZW5zdGFjayIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwMC92MS8iLCAiaWQiOiAiNWU4ZjExYzk3ZTgwNDNiNWJkZTA1YmVhMmRlNDYxNmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODAwMC92MS8ifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiY2xvdWRmb3JtYXRpb24iLCAibmFtZSI6ICJoZWF0LWNmbiJ9LCB7ImVuZHBvaW50cyI6IFt7ImFkbWluVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4Nzc2L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgInJlZ2lvbiI6ICJvcGVuc3RhY2siLCAiaW50ZXJuYWxVUkwiOiAiaHR0cDovLzE3Mi4xNi4zMy40Ojg3NzYvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUiLCAiaWQiOiAiNTRiOWVjMjhiYzYwNDI1MmIwMGNmZTZlMGU0NGFhOTQiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6ODc3Ni92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJ2b2x1bWUiLCAibmFtZSI6ICJjaW5kZXIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODc3My9zZXJ2aWNlcy9BZG1pbiIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4NzczL3NlcnZpY2VzL0Nsb3VkIiwgImlkIjogIjA3NWVjNzliMGJlMzQxYmFhYmUyZTliMTIwNTkxZjQ4IiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40Ojg3NzMvc2VydmljZXMvQ2xvdWQifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAiZWMyIiwgIm5hbWUiOiAibm92YV9lYzIifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6ODAwNC92MS9jNTE4YjM2ZmEyMjA0OTliODViYTlhNzEwMTRjZTJhNSIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo4MDA0L3YxL2M1MThiMzZmYTIyMDQ5OWI4NWJhOWE3MTAxNGNlMmE1IiwgImlkIjogIjI2MmM0YjM3MzY3ODQ2OGE5ODU1YTNlYmM2MDE1OTYwIiwgInB1YmxpY1VSTCI6ICJodHRwOi8vMTkyLjE2OC4xMS40OjgwMDQvdjEvYzUxOGIzNmZhMjIwNDk5Yjg1YmE5YTcxMDE0Y2UyYTUifV0sICJlbmRwb2ludHNfbGlua3MiOiBbXSwgInR5cGUiOiAib3JjaGVzdHJhdGlvbiIsICJuYW1lIjogImhlYXQifSwgeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTcyLjE2LjMzLjQ6MzUzNTcvdjIuMCIsICJyZWdpb24iOiAib3BlbnN0YWNrIiwgImludGVybmFsVVJMIjogImh0dHA6Ly8xNzIuMTYuMzMuNDo1MDAwL3YyLjAiLCAiaWQiOiAiMDg5ZmRiMjIyNDk1NDZiOTlhMWU1N2FlYzBiMWU3NmMiLCAicHVibGljVVJMIjogImh0dHA6Ly8xOTIuMTY4LjExLjQ6NTAwMC92Mi4wIn1dLCAiZW5kcG9pbnRzX2xpbmtzIjogW10sICJ0eXBlIjogImlkZW50aXR5IiwgIm5hbWUiOiAia2V5c3RvbmUifV0sICJ1c2VyIjogeyJ1c2VybmFtZSI6ICJhZG1pbiIsICJyb2xlc19saW5rcyI6IFtdLCAiaWQiOiAiM2Y3NmI5NDY2NzQzNGNmM2JkYzMyM2NmMDIxYzUwZjgiLCAicm9sZXMiOiBbeyJuYW1lIjogImFkbWluIn1dLCAibmFtZSI6ICJhZG1pbiJ9LCAibWV0YWRhdGEiOiB7ImlzX2FkbWluIjogMCwgInJvbGVzIjogWyIxZThiYzVkMWYzYTQ0OGU5YTJhMWNkYTU4ZDk3ZjkyYiJdfX19MYIBgTCCAX0CAQEwXDBXMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVW5zZXQxDjAMBgNVBAcMBVVuc2V0MQ4wDAYDVQQKDAVVbnNldDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tAgEBMAcGBSsOAwIaMA0GCSqGSIb3DQEBAQUABIIBAEOAl3MRmSUB+J+kRi+qRhwOrNRmj-wDqT5nJTlbafOjofSXsHG683LaipA7oPoH-ARUPDxXIZfevRue7bQQB3I4cWIUSItIPyW4xDpF+iHy3QOm+I-3v3ctze2Z3Rp0TRaYFsItTZZETsSXI28yBt9+3Dsk3a7Vv10HAZetbV1i6qu6avLcJsmN-1J3KLwCDSEvpMgDAcpzAnhba1fi+X8GrCCTz4c1uIcPfsHxX4g8gNkB4-VT0lkRmfSxdrGeRz0uN12oDqgCL64IV1mJ6Bi9Unh15QFcLwU0F8ote+joG9G29fw3WDzneXHIeEIZSBXmOAX2kQBOnZa2sZg8gls="
-      response: 
-        status: 
-          code: 200
-          message: 
-        headers: 
-          vary: 
-            - X-Auth-Token
-          content-type: 
-            - application/json
-          content-length: 
-            - "143"
-          date: 
-            - "Tue, 30 Sep 2014 07:16:15 GMT"
-          connection: 
-            - close
-        body: 
-          encoding: UTF-8
-          string: "{\x22tenants_links\x22: [], \x22tenants\x22: [{\x22description\x22: \x22admin tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c518b36fa220499b85ba9a71014ce2a5\x22, \x22name\x22: \x22admin\x22}]}"
-        http_version: 
-      recorded_at: "Tue, 30 Sep 2014 07:16:15 GMT"
-  recorded_with: "VCR 2.9.3"
\ No newline at end of file
diff --git a/3rdparty/modules/openstacklib/spec/fixtures/vcr/aviator/session/with_token.yml b/3rdparty/modules/openstacklib/spec/fixtures/vcr/aviator/session/with_token.yml
deleted file mode 100644 (file)
index 784fb2f..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
---- 
-  http_interactions: 
-    - request: 
-        method: get
-        uri: "http://192.168.11.4:35357/v2.0/tenants"
-        body: 
-          encoding: US-ASCII
-          string: ""
-        headers: 
-          Content-Type: 
-            - application/json
-          User-Agent: 
-            - "Faraday v0.8.8"
-          X-Auth-Token: 
-            - sosp-kyl
-      response: 
-        status: 
-          code: 200
-          message: 
-        headers: 
-          vary: 
-            - X-Auth-Token
-          content-type: 
-            - application/json
-          content-length: 
-            - "491"
-          date: 
-            - "Tue, 30 Sep 2014 06:59:48 GMT"
-          connection: 
-            - close
-        body: 
-          encoding: UTF-8
-          string: "{\x22tenants_links\x22: [], \x22tenants\x22: [{\x22description\x22: \x22Test tenant\x22, \x22enabled\x22: true, \x22id\x22: \x2234e463e2bab24f78990ca864e4a28ba2\x22, \x22name\x22: \x22test2\x22}, {\x22description\x22: \x22Tenant for the openstack services\x22, \x22enabled\x22: true, \x22id\x22: \x2268c8fcf77aff4b409cc158c0f6cbff7b\x22, \x22name\x22: \x22services\x22}, {\x22description\x22: \x22Test tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c330f1bc663648df9c1e7835a1e7a955\x22, \x22name\x22: \x22test\x22}, {\x22description\x22: \x22admin tenant\x22, \x22enabled\x22: true, \x22id\x22: \x22c518b36fa220499b85ba9a71014ce2a5\x22, \x22name\x22: \x22admin\x22}]}"
-        http_version: 
-      recorded_at: "Tue, 30 Sep 2014 06:59:48 GMT"
-  recorded_with: "VCR 2.9.3"
\ No newline at end of file
index 6819e7e8f4bd0abc53e6d4782569f82ecaebf8d7..62d03f21a0ea5f1a5452888afaf86f16ce7360b8 100644 (file)
@@ -3,27 +3,27 @@ require 'spec_helper'
 describe 'os_database_connection' do
 
   it 'refuses String' do
-    should run.with_params('foo').\
+    is_expected.to run.with_params('foo').\
       and_raise_error(Puppet::ParseError, /Requires an hash/)
   end
 
   it 'refuses Array' do
-    should run.with_params(['foo']).\
+    is_expected.to run.with_params(['foo']).\
       and_raise_error(Puppet::ParseError, /Requires an hash/)
   end
 
   it 'refuses without at least one argument' do
-    should run.with_params().\
+    is_expected.to run.with_params().\
       and_raise_error(Puppet::ParseError, /Wrong number of arguments/)
   end
 
   it 'refuses too many arguments' do
-    should run.with_params('foo', 'bar').\
+    is_expected.to run.with_params('foo', 'bar').\
       and_raise_error(Puppet::ParseError, /Wrong number of arguments/)
   end
 
   it 'fails if port is provided with missing host' do
-    should run.with_params({
+    is_expected.to run.with_params({
         'dialect'  => 'sqlite',
         'database' => '/var/lib/keystone/keystone.db',
         'port'     => '3306',
@@ -34,7 +34,7 @@ describe 'os_database_connection' do
   context 'creates the correct connection URI' do
 
     it 'with all parameters' do
-      should run.with_params({
+      is_expected.to run.with_params({
           'dialect'  => 'mysql',
           'host'     => '127.0.0.1',
           'port'     => '3306',
@@ -46,7 +46,7 @@ describe 'os_database_connection' do
     end
 
     it 'without port' do
-      should run.with_params({
+      is_expected.to run.with_params({
           'dialect'  => 'mysql',
           'host'     => '127.0.0.1',
           'database' => 'test',
@@ -57,7 +57,7 @@ describe 'os_database_connection' do
     end
 
     it 'without host and port' do
-      should run.with_params({
+      is_expected.to run.with_params({
           'dialect'  => 'sqlite',
           'database' => '/var/lib/keystone/keystone.db',
           'charset'  => 'utf-8'
@@ -65,7 +65,7 @@ describe 'os_database_connection' do
     end
 
     it 'without username and password' do
-      should run.with_params({
+      is_expected.to run.with_params({
           'dialect'  => 'mysql',
           'host'     => '127.0.0.1',
           'port'     => '3306',
@@ -75,7 +75,7 @@ describe 'os_database_connection' do
     end
 
     it 'with username set to undef' do
-      should run.with_params({
+      is_expected.to run.with_params({
           'dialect'  => 'mysql',
           'host'     => '127.0.0.1',
           'port'     => '3306',
@@ -86,7 +86,7 @@ describe 'os_database_connection' do
     end
 
     it 'with username set to an empty string' do
-      should run.with_params({
+      is_expected.to run.with_params({
           'dialect'  => 'mysql',
           'host'     => '127.0.0.1',
           'port'     => '3306',
@@ -97,7 +97,7 @@ describe 'os_database_connection' do
     end
 
     it 'without password' do
-      should run.with_params({
+      is_expected.to run.with_params({
           'dialect'  => 'mysql',
           'host'     => '127.0.0.1',
           'port'     => '3306',
@@ -108,7 +108,7 @@ describe 'os_database_connection' do
     end
 
     it 'with password set to undef' do
-      should run.with_params({
+      is_expected.to run.with_params({
           'dialect'  => 'mysql',
           'host'     => '127.0.0.1',
           'port'     => '3306',
@@ -120,7 +120,7 @@ describe 'os_database_connection' do
     end
 
     it 'with password set to an empty string' do
-      should run.with_params({
+      is_expected.to run.with_params({
           'dialect'  => 'mysql',
           'host'     => '127.0.0.1',
           'port'     => '3306',
diff --git a/3rdparty/modules/openstacklib/spec/shared_examples.rb b/3rdparty/modules/openstacklib/spec/shared_examples.rb
new file mode 100644 (file)
index 0000000..fec0eac
--- /dev/null
@@ -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
index ecd609ae7d262f67d7245151d891d1097608df30..53d4dd02de495692f96839152f6058dfff107ad1 100644 (file)
@@ -1,7 +1,7 @@
 require 'puppetlabs_spec_helper/module_spec_helper'
-require 'vcr'
+require 'shared_examples'
 
-VCR.configure do |c|
-  c.cassette_library_dir = 'spec/fixtures/vcr'
-  c.hook_into :faraday
+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
diff --git a/3rdparty/modules/openstacklib/spec/spec_helper_acceptance.rb b/3rdparty/modules/openstacklib/spec/spec_helper_acceptance.rb
new file mode 100644 (file)
index 0000000..1879cbf
--- /dev/null
@@ -0,0 +1,42 @@
+require 'beaker-rspec'
+
+hosts.each do |host|
+
+  install_puppet
+
+  on host, "mkdir -p #{host['distmoduledir']}"
+end
+
+RSpec.configure do |c|
+  # Project root
+  proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+
+  # Readable test descriptions
+  c.formatter = :documentation
+
+  # Configure all nodes in nodeset
+  c.before :suite do
+    # Install module and dependencies
+    hosts.each do |host|
+
+      # install git
+      install_package host, 'git'
+
+      # clean out any module cruft
+      shell('rm -fr /etc/puppet/modules/*')
+
+      # install library modules from the forge
+      on host, puppet('module','install','puppetlabs-mysql'), { :acceptable_exit_codes => 0 }
+      on host, puppet('module','install','puppetlabs-apache'), { :acceptable_exit_codes => 0 }
+      on host, puppet('module','install','puppetlabs-postgresql'), { :acceptable_exit_codes => 0 }
+      on host, puppet('module','install','stahnma-epel'), { :acceptable_exit_codes => 0 }
+      # until https://github.com/tamaskozak/puppetlabs-rabbitmq/commit/8bbfe320035fae2ae900211501008d63dc3c171c is part of a release
+      shell('git clone https://github.com/puppetlabs/puppetlabs-rabbitmq /etc/puppet/modules/rabbitmq')
+      shell('git clone https://git.openstack.org/openstack/puppet-openstack_extras /etc/puppet/modules/openstack_extras')
+      # Install the module being tested
+      puppet_module_install(:source => proj_root, :module_name => 'openstacklib')
+      # List modules installed to help with debugging
+      on hosts[0], puppet('module','list'), { :acceptable_exit_codes => 0 }
+    end
+  end
+end
diff --git a/3rdparty/modules/openstacklib/spec/unit/provider/aviator_spec.rb b/3rdparty/modules/openstacklib/spec/unit/provider/aviator_spec.rb
deleted file mode 100644 (file)
index 35564e6..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-# Load libraries from aviator here to simulate how they live together in a real puppet run
-$LOAD_PATH.push(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'modules', 'aviator', 'lib'))
-require 'puppet'
-require 'vcr'
-require 'spec_helper'
-require 'puppet/provider/aviator'
-
-
-describe Puppet::Provider::Aviator do
-
-  before(:each) do
-    ENV['OS_USERNAME']    = nil
-    ENV['OS_PASSWORD']    = nil
-    ENV['OS_TENANT_NAME'] = nil
-    ENV['OS_AUTH_URL']    = nil
-  end
-
-  let(:log_file) { '/tmp/aviator_spec.log' }
-
-  let(:type) do
-    Puppet::Type.newtype(:test_resource) do
-      newparam(:name, :namevar => true)
-      newparam(:auth)
-      newparam(:log_file)
-    end
-  end
-
-
-  shared_examples 'creating a session using environment variables' do
-    it 'creates an authenticated session' do
-      ENV['OS_USERNAME']    = 'admin'
-      ENV['OS_PASSWORD']    = 'fyby-tet'
-      ENV['OS_TENANT_NAME'] = 'admin'
-      ENV['OS_AUTH_URL']    = 'http://192.168.11.4:35357/v2.0'
-      response = nil
-      VCR.use_cassette('aviator/session/with_password') do
-        session = provider.session
-        response = session.identity_service.request(:list_tenants, :session_data => provider.session_data)
-      end
-      expect(response.status).to eq(200)
-    end
-  end
-
-  shared_examples 'creating a session using a service token from keystone.conf' do
-    it 'creates an unauthenticated session' do
-      data = "[DEFAULT]\nadmin_token=sosp-kyl\nadmin_endpoint=http://192.168.11.4:35357/v2.0"
-      response = nil
-      VCR.use_cassette('aviator/session/with_token') do
-        # Stubbing File.read produces inconsistent results because of how IniConfig
-        # overrides the File class in some versions of Puppet.
-        # Stubbing FileType.filetype(:flat) simplifies working with IniConfig
-        Puppet::Util::FileType.filetype(:flat).any_instance.expects(:read).returns(StringIO.new(data).read)
-        session = provider.session
-        Puppet::Util::FileType.filetype(:flat).any_instance.unstub(:read)
-        response = session.identity_service.request(:list_tenants, :session_data => provider.session_data)
-      end
-
-      expect(response.status).to eq(200)
-    end
-  end
-
-  shared_examples 'it has no credentials' do
-    it 'fails to authenticate' do
-      expect{ provider.session }.to raise_error(Puppet::Error, /No credentials provided/)
-    end
-  end
-
-  shared_examples 'making request with an existing session' do
-   it 'makes a successful request' do
-     VCR.use_cassette('aviator/request/with_session') do
-       session = provider.session
-       response = provider.request(session.identity_service, :list_tenants)
-       expect(response.status).to eq(200)
-     end
-   end
-  end
-
-  shared_examples 'making request with injected session data' do
-    it 'makes a successful request' do
-      VCR.use_cassette('aviator/request/without_session') do
-        session = provider.session
-        response = provider.request(session.identity_service, :list_tenants)
-        expect(response.status).to eq(200)
-      end
-    end
-  end
-
-  shared_examples 'making request with no session or session data' do
-    it 'fails to make a request' do
-      expect{ provider.request(nil, :list_tenants) }.to raise_error(Puppet::Error, /Cannot make a request/)
-    end
-  end
-
-  describe '#session' do
-
-    context 'with valid password credentials in parameters' do
-      let(:resource_attrs) do
-        {
-          :name         => 'stubresource',
-          :auth         => {
-            'username'    => 'admin',
-            'password'    => 'fyby-tet',
-            'tenant_name' => 'admin',
-            'host_uri'    => 'http://192.168.11.4:35357/v2.0',
-          }
-        }
-      end
-
-      it 'creates a session' do
-        provider = Puppet::Provider::Aviator.new(type.new(resource_attrs))
-        response = nil
-        VCR.use_cassette('aviator/session/with_password') do
-          session = provider.session
-          response = session.identity_service.request(:list_tenants)
-        end
-        expect(response.status).to eq(200)
-      end
-    end
-
-    context 'with valid openrc file in parameters' do
-      data = "export OS_USERNAME='admin'\nexport OS_PASSWORD='fyby-tet'\nexport OS_TENANT_NAME='admin'\nexport OS_AUTH_URL='http://192.168.11.4:35357/v2.0'"
-      let(:resource_attrs) do
-        {
-          :name         => 'stubresource',
-          :auth         => {
-            'openrc' => '/root/openrc'
-          }
-        }
-      end
-
-      it 'creates a session' do
-        provider = Puppet::Provider::Aviator.new(type.new(resource_attrs))
-        response = nil
-        VCR.use_cassette('aviator/session/with_password') do
-          File.expects(:open).with('/root/openrc').returns(StringIO.new(data))
-          session = provider.session
-          File.unstub(:open)  # Ignore File.open calls to cassette file
-          response = session.identity_service.request(:list_tenants)
-        end
-        expect(response.status).to eq(200)
-      end
-    end
-
-    context 'with valid service token in parameters' do
-      let(:resource_attrs) do
-        {
-          :name         => 'stubresource',
-          :auth         => {
-            'service_token' => 'sosp-kyl',
-            'host_uri'      => 'http://192.168.11.4:35357/v2.0'
-          }
-        }
-      end
-
-      subject(:session) do
-        provider = Puppet::Provider::Aviator.new(type.new(resource_attrs))
-        VCR.use_cassette('aviator/session/with_token') do
-          session = provider.session
-          response = session.identity_service.request(:list_tenants, :session_data => provider.session_data)
-        end
-      end
-
-      it 'creates a session' do
-        expect(session.status).to eq(200)
-      end
-
-    end
-
-    context 'with valid password credentials in environment variables' do
-      it_behaves_like 'creating a session using environment variables' do
-        let(:resource_attrs) do
-          {
-            :name => 'stubresource',
-          }
-        end
-        let(:provider) do
-          Puppet::Provider::Aviator.new(type.new(resource_attrs))
-        end
-      end
-    end
-
-    context 'with valid service token in keystone.conf' do
-      it_behaves_like 'creating a session using a service token from keystone.conf' do
-        let(:resource_attrs) do
-          {
-            :name => 'stubresource',
-          }
-        end
-        let(:provider) do
-          Puppet::Provider::Aviator.new(type.new(resource_attrs))
-        end
-      end
-
-    end
-
-    context 'with no valid credentials' do
-      it_behaves_like 'it has no credentials' do
-        let(:resource_attrs) do
-          {
-            :name => 'stubresource',
-          }
-        end
-        let(:provider) { Puppet::Provider::Aviator.new(type.new(resource_attrs)) }
-      end
-    end
-
-  end
-
-
-  describe '::session' do
-
-    context 'with valid password credentials in environment variables' do
-      it_behaves_like 'creating a session using environment variables' do
-        let(:provider) { Puppet::Provider::Aviator.dup }
-      end
-    end
-
-    context 'with valid service token in keystone.conf' do
-      it_behaves_like 'creating a session using a service token from keystone.conf' do
-        let(:provider) { Puppet::Provider::Aviator.dup }
-      end
-    end
-
-    context 'with no valid credentials' do
-      it_behaves_like 'it has no credentials' do
-        let(:provider) { Puppet::Provider::Aviator.dup }
-      end
-    end
-  end
-
-  describe '#request' do
-    context 'when a session exists' do
-      it_behaves_like 'making request with an existing session' do
-        let(:resource_attrs) do
-          {
-            :name         => 'stubresource',
-            :auth         => {
-              'username'    => 'admin',
-              'password'    => 'fyby-tet',
-              'tenant_name' => 'admin',
-              'host_uri'    => 'http://192.168.11.4:35357/v2.0',
-            }
-          }
-        end
-        let (:provider) { Puppet::Provider::Aviator.new(type.new(resource_attrs)) }
-      end
-    end
-
-    context 'when injecting session data' do
-      let(:resource_attrs) do
-        {
-          :name         => 'stubresource',
-          :auth         => {
-            'service_token' => 'sosp-kyl',
-            'host_uri'      => 'http://192.168.11.4:35357/v2.0'
-          }
-        }
-      end
-      let(:provider) { Puppet::Provider::Aviator.new(type.new(resource_attrs)) }
-      it 'makes a successful request' do
-        provider = Puppet::Provider::Aviator.new(type.new(resource_attrs))
-        VCR.use_cassette('aviator/request/without_session') do
-          session = provider.session
-          response = provider.request(session.identity_service, :list_tenants)
-          expect(response.status).to eq(200)
-        end
-      end
-    end
-
-    context 'when there is no session or session data' do
-      it_behaves_like 'making request with no session or session data' do
-        let(:resource_attrs) do
-          {
-            :name => 'stubresource',
-          }
-        end
-        let(:provider) {Puppet::Provider::Aviator.new(type.new(resource_attrs)) }
-      end
-    end
-  end
-
-  describe '::request' do
-    context 'when a session exists' do
-
-      it_behaves_like 'making request with an existing session' do
-        let(:provider) { provider = Puppet::Provider::Aviator.dup }
-        before(:each) do
-          ENV['OS_USERNAME']    = 'admin'
-          ENV['OS_PASSWORD']    = 'fyby-tet'
-          ENV['OS_TENANT_NAME'] = 'admin'
-          ENV['OS_AUTH_URL']    = 'http://192.168.11.4:35357/v2.0'
-        end
-      end
-    end
-
-    context 'when injecting session data' do
-      let(:session_data) do
-        {
-          :base_url      => 'http://192.168.11.4:35357/v2.0',
-          :service_token => 'sosp-kyl'
-        }
-      end
-      it 'makes a successful request' do
-        provider = Puppet::Provider::Aviator.dup
-        VCR.use_cassette('aviator/request/without_session') do
-          session = ::Aviator::Session.new(:config => { :provider => 'openstack' }, :log_file => log_file)
-          provider.session_data = session_data
-          response = provider.request(session.identity_service, :list_tenants)
-          expect(response.status).to eq(200)
-        end
-      end
-    end
-
-    context 'when there is no session or session data' do
-      it_behaves_like 'making request with no session or session data' do
-        let(:provider) { Puppet::Provider::Aviator.dup }
-      end
-    end
-  end
-end
diff --git a/3rdparty/modules/openstacklib/spec/unit/provider/openstack/auth_spec.rb b/3rdparty/modules/openstacklib/spec/unit/provider/openstack/auth_spec.rb
new file mode 100644 (file)
index 0000000..7a25944
--- /dev/null
@@ -0,0 +1,222 @@
+require 'puppet'
+require 'spec_helper'
+require 'puppet/provider/openstack'
+require 'puppet/provider/openstack/auth'
+require 'tempfile'
+
+class Puppet::Provider::Openstack::AuthTester < Puppet::Provider::Openstack
+  extend Puppet::Provider::Openstack::Auth
+end
+
+klass = Puppet::Provider::Openstack::AuthTester
+
+describe Puppet::Provider::Openstack::Auth do
+
+  let(:type) do
+    Puppet::Type.newtype(:test_resource) do
+      newparam(:name, :namevar => true)
+      newparam(:log_file)
+    end
+  end
+
+  let(:resource_attrs) do
+    {
+      :name => 'stubresource'
+    }
+  end
+
+  let(:provider) do
+    klass.new(type.new(resource_attrs))
+  end
+
+  before(:each) do
+    ENV['OS_USERNAME']     = nil
+    ENV['OS_PASSWORD']     = nil
+    ENV['OS_PROJECT_NAME'] = nil
+    ENV['OS_AUTH_URL']     = nil
+    ENV['OS_TOKEN']        = nil
+    ENV['OS_URL']          = nil
+  end
+
+  describe '#set_credentials' do
+    it 'adds keys to the object' do
+      credentials = Puppet::Provider::Openstack::CredentialsV2_0.new
+      set = { 'OS_USERNAME'             => 'user',
+              'OS_PASSWORD'             => 'secret',
+              'OS_PROJECT_NAME'         => 'tenant',
+              'OS_AUTH_URL'             => 'http://127.0.0.1:5000',
+              'OS_TOKEN'                => 'token',
+              'OS_URL'                  => 'http://127.0.0.1:35357',
+              'OS_IDENTITY_API_VERSION' => '2.0',
+              'OS_NOT_VALID'            => 'notvalid'
+        }
+      klass.set_credentials(credentials, set)
+      expect(credentials.to_env).to eq(
+        "OS_AUTH_URL"             => "http://127.0.0.1:5000",
+        "OS_IDENTITY_API_VERSION" => '2.0',
+        "OS_PASSWORD"             => "secret",
+        "OS_PROJECT_NAME"         => "tenant",
+        "OS_TOKEN"                => "token",
+        "OS_URL"                  => "http://127.0.0.1:35357",
+        "OS_USERNAME"             => "user")
+    end
+  end
+
+  describe '#rc_filename' do
+    it 'returns RCFILENAME' do
+      expect(klass.rc_filename).to eq("#{ENV['HOME']}/openrc")
+    end
+  end
+
+  describe '#get_os_from_env' do
+    context 'with Openstack environment variables set' do
+      it 'provides a hash' do
+        ENV['OS_AUTH_URL']     = 'http://127.0.0.1:5000'
+        ENV['OS_PASSWORD']     = 'abc123'
+        ENV['OS_PROJECT_NAME'] = 'test'
+        ENV['OS_USERNAME']     = 'test'
+        response = klass.get_os_vars_from_env
+        expect(response).to eq({
+          "OS_AUTH_URL"     => "http://127.0.0.1:5000",
+          "OS_PASSWORD"     => "abc123",
+          "OS_PROJECT_NAME" => "test",
+          "OS_USERNAME"     => "test"})
+      end
+    end
+  end
+
+  describe '#get_os_vars_from_rcfile' do
+    context 'with a valid RC file' do
+      it 'provides a hash' do
+        mock = "export OS_USERNAME='test'\nexport OS_PASSWORD='abc123'\nexport OS_PROJECT_NAME='test'\nexport OS_AUTH_URL='http://127.0.0.1:5000'"
+        filename = 'file'
+        File.expects(:exists?).with('file').returns(true)
+        File.expects(:open).with('file').returns(StringIO.new(mock))
+
+        response = klass.get_os_vars_from_rcfile(filename)
+        expect(response).to eq({
+          "OS_AUTH_URL"     => "http://127.0.0.1:5000",
+          "OS_PASSWORD"     => "abc123",
+          "OS_PROJECT_NAME" => "test",
+          "OS_USERNAME"     => "test"})
+      end
+    end
+
+    context 'with an empty file' do
+      it 'provides an empty hash' do
+        filename = 'file'
+        File.expects(:exists?).with(filename).returns(true)
+        File.expects(:open).with(filename).returns(StringIO.new(""))
+
+        response = klass.get_os_vars_from_rcfile(filename)
+        expect(response).to eq({})
+      end
+    end
+  end
+
+  before(:each) do
+    class Puppet::Provider::Openstack::AuthTester
+      @credentials =  Puppet::Provider::Openstack::CredentialsV2_0.new
+    end
+  end
+
+  describe '#request' do
+    context 'with no valid credentials' do
+      it 'fails to authenticate' do
+        expect { klass.request('project', 'list', ['--long']) }.to raise_error(Puppet::Error::OpenstackAuthInputError, "Insufficient credentials to authenticate")
+        expect(klass.instance_variable_get(:@credentials).to_env).to eq({})
+      end
+    end
+
+    context 'with user credentials in env' do
+      it 'is successful' do
+        klass.expects(:get_os_vars_from_env)
+             .returns({ 'OS_USERNAME'     => 'test',
+                        'OS_PASSWORD'     => 'abc123',
+                        'OS_PROJECT_NAME' => 'test',
+                        'OS_AUTH_URL'     => 'http://127.0.0.1:5000',
+                        'OS_NOT_VALID'    => 'notvalid' })
+        klass.expects(:openstack)
+             .with('project', 'list', '--quiet', '--format', 'csv', ['--long'])
+             .returns('"ID","Name","Description","Enabled"
+"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
+')
+        response = klass.request('project', 'list', ['--long'])
+        expect(response.first[:description]).to eq("Test tenant")
+        expect(klass.instance_variable_get(:@credentials).to_env).to eq({
+          'OS_USERNAME'     => 'test',
+          'OS_PASSWORD'     => 'abc123',
+          'OS_PROJECT_NAME' => 'test',
+          'OS_AUTH_URL'     => 'http://127.0.0.1:5000'
+        })
+      end
+    end
+
+    context 'with service token credentials in env' do
+      it 'is successful' do
+        klass.expects(:get_os_vars_from_env)
+             .returns({ 'OS_TOKEN'     => 'test',
+                        'OS_URL'       => 'http://127.0.0.1:5000',
+                        'OS_NOT_VALID' => 'notvalid' })
+        klass.expects(:openstack)
+             .with('project', 'list', '--quiet', '--format', 'csv', ['--long'])
+             .returns('"ID","Name","Description","Enabled"
+"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
+')
+        response = klass.request('project', 'list', ['--long'])
+        expect(response.first[:description]).to eq("Test tenant")
+        expect(klass.instance_variable_get(:@credentials).to_env).to eq({
+          'OS_TOKEN' => 'test',
+          'OS_URL'   => 'http://127.0.0.1:5000',
+        })
+      end
+    end
+
+    context 'with a RC file containing user credentials' do
+      it 'is successful' do
+        # return incomplete creds from env
+        klass.expects(:get_os_vars_from_env)
+             .returns({ 'OS_USERNAME' => 'incompleteusername',
+                        'OS_AUTH_URL' => 'incompleteauthurl' })
+        mock = "export OS_USERNAME='test'\nexport OS_PASSWORD='abc123'\nexport OS_PROJECT_NAME='test'\nexport OS_AUTH_URL='http://127.0.0.1:5000'\nexport OS_NOT_VALID='notvalid'"
+        File.expects(:exists?).with("#{ENV['HOME']}/openrc").returns(true)
+        File.expects(:open).with("#{ENV['HOME']}/openrc").returns(StringIO.new(mock))
+        klass.expects(:openstack)
+             .with('project', 'list', '--quiet', '--format', 'csv', ['--long'])
+             .returns('"ID","Name","Description","Enabled"
+"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
+')
+        response = provider.class.request('project', 'list', ['--long'])
+        expect(response.first[:description]).to eq("Test tenant")
+        expect(klass.instance_variable_get(:@credentials).to_env).to eq({
+          'OS_USERNAME'     => 'test',
+          'OS_PASSWORD'     => 'abc123',
+          'OS_PROJECT_NAME' => 'test',
+          'OS_AUTH_URL'     => 'http://127.0.0.1:5000'
+        })
+      end
+    end
+
+    context 'with a RC file containing service token credentials' do
+      it 'is successful' do
+        # return incomplete creds from env
+        klass.expects(:get_os_vars_from_env)
+             .returns({ 'OS_TOKEN' => 'incomplete' })
+        mock = "export OS_TOKEN='test'\nexport OS_URL='abc123'\nexport OS_NOT_VALID='notvalid'\n"
+        File.expects(:exists?).with("#{ENV['HOME']}/openrc").returns(true)
+        File.expects(:open).with("#{ENV['HOME']}/openrc").returns(StringIO.new(mock))
+        klass.expects(:openstack)
+             .with('project', 'list', '--quiet', '--format', 'csv', ['--long'])
+             .returns('"ID","Name","Description","Enabled"
+"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
+')
+        response = klass.request('project', 'list', ['--long'])
+        expect(response.first[:description]).to eq("Test tenant")
+        expect(klass.instance_variable_get(:@credentials).to_env).to eq({
+          'OS_TOKEN' => 'test',
+          'OS_URL'   => 'abc123',
+        })
+      end
+    end
+  end
+end
diff --git a/3rdparty/modules/openstacklib/spec/unit/provider/openstack/credentials_spec.rb b/3rdparty/modules/openstacklib/spec/unit/provider/openstack/credentials_spec.rb
new file mode 100644 (file)
index 0000000..aa81ec2
--- /dev/null
@@ -0,0 +1,158 @@
+require 'puppet'
+require 'spec_helper'
+require 'puppet/provider/openstack'
+require 'puppet/provider/openstack/credentials'
+
+
+describe Puppet::Provider::Openstack::Credentials do
+
+  let(:creds) do
+    creds = Puppet::Provider::Openstack::CredentialsV2_0.new
+  end
+
+  describe "#set with valid value" do
+    it 'works with valid value' do
+      expect(creds.class.defined?('auth_url')).to be_truthy
+      creds.set('auth_url', 'http://localhost:5000/v2.0')
+      expect(creds.auth_url).to eq('http://localhost:5000/v2.0')
+    end
+  end
+
+  describe "#set with invalid value" do
+    it 'works with invalid value' do
+      expect(creds.class.defined?('foo')).to be_falsey
+      creds.set('foo', 'junk')
+      expect(creds.respond_to?(:foo)).to be_falsey
+      expect(creds.instance_variable_defined?(:@foo)).to be_falsey
+      expect { creds.foo }.to raise_error(NoMethodError, /undefined method/)
+    end
+  end
+
+  describe '#service_token_set?' do
+    context "with service credentials" do
+      it 'is successful' do
+        creds.token = 'token'
+        creds.url = 'url'
+        expect(creds.service_token_set?).to be_truthy
+        expect(creds.user_password_set?).to be_falsey
+      end
+
+      it 'fails' do
+        creds.token = 'token'
+        expect(creds.service_token_set?).to be_falsey
+        expect(creds.user_password_set?).to be_falsey
+      end
+    end
+  end
+
+  describe '#password_set?' do
+    context "with user credentials" do
+      it 'is successful' do
+        creds.auth_url = 'auth_url'
+        creds.password = 'password'
+        creds.project_name = 'project_name'
+        creds.username = 'username'
+        expect(creds.user_password_set?).to be_truthy
+        expect(creds.service_token_set?).to be_falsey
+      end
+
+      it 'fails' do
+        creds.auth_url = 'auth_url'
+        creds.password = 'password'
+        creds.project_name = 'project_name'
+        expect(creds.user_password_set?).to be_falsey
+        expect(creds.service_token_set?).to be_falsey
+      end
+    end
+  end
+
+  describe '#set?' do
+    context "without any credential" do
+      it 'fails' do
+        expect(creds.set?).to be_falsey
+      end
+    end
+  end
+
+  describe '#version' do
+    it 'is version 2' do
+      expect(creds.version).to eq('2.0')
+    end
+  end
+
+  describe '#unset' do
+    context "with all instance variables set" do
+      it 'resets all but the identity_api_version' do
+        creds.auth_url = 'auth_url'
+        creds.password = 'password'
+        creds.project_name = 'project_name'
+        creds.username = 'username'
+        creds.token = 'token'
+        creds.url = 'url'
+        creds.identity_api_version = 'identity_api_version'
+        creds.unset
+        expect(creds.auth_url).to eq('')
+        expect(creds.password).to eq('')
+        expect(creds.project_name).to eq('')
+        expect(creds.username).to eq('')
+        expect(creds.token).to eq('')
+        expect(creds.url).to eq('')
+        expect(creds.identity_api_version).to eq('identity_api_version')
+        newcreds = Puppet::Provider::Openstack::CredentialsV3.new
+        expect(newcreds.identity_api_version).to eq('3')
+      end
+    end
+  end
+
+  describe '#to_env' do
+    context "with an exhaustive data set" do
+      it 'successfully returns content' do
+        creds.auth_url = 'auth_url'
+        creds.password = 'password'
+        creds.project_name = 'project_name'
+        creds.username = 'username'
+        creds.token = 'token'
+        creds.url = 'url'
+        creds.identity_api_version = 'identity_api_version'
+        expect(creds.to_env).to eq({
+          'OS_USERNAME'             => 'username',
+          'OS_PASSWORD'             => 'password',
+          'OS_PROJECT_NAME'         => 'project_name',
+          'OS_AUTH_URL'             => 'auth_url',
+          'OS_TOKEN'                => 'token',
+          'OS_URL'                  => 'url',
+          'OS_IDENTITY_API_VERSION' => 'identity_api_version'
+        })
+      end
+    end
+  end
+
+  describe 'using v3' do
+    let(:creds) do
+      creds = Puppet::Provider::Openstack::CredentialsV3.new
+    end
+    describe 'with v3' do
+      it 'uses v3 identity api' do
+        creds.identity_api_version == '3'
+      end
+    end
+    describe '#password_set? with username and project_name' do
+      it 'is successful' do
+        creds.auth_url = 'auth_url'
+        creds.password = 'password'
+        creds.project_name = 'project_name'
+        creds.username = 'username'
+        expect(creds.user_password_set?).to be_truthy
+      end
+    end
+    describe '#password_set? with user_id and project_id' do
+      it 'is successful' do
+        creds.auth_url = 'auth_url'
+        creds.password = 'password'
+        creds.project_id = 'projid'
+        creds.user_id = 'userid'
+        expect(creds.user_password_set?).to be_truthy
+      end
+    end
+  end
+end
diff --git a/3rdparty/modules/openstacklib/spec/unit/provider/openstack_spec.rb b/3rdparty/modules/openstacklib/spec/unit/provider/openstack_spec.rb
new file mode 100644 (file)
index 0000000..c9c22ee
--- /dev/null
@@ -0,0 +1,89 @@
+require 'puppet'
+require 'spec_helper'
+require 'puppet/provider/openstack'
+
+describe Puppet::Provider::Openstack do
+  before(:each) do
+    ENV['OS_USERNAME']     = nil
+    ENV['OS_PASSWORD']     = nil
+    ENV['OS_PROJECT_NAME'] = nil
+    ENV['OS_AUTH_URL']     = nil
+  end
+
+  let(:type) do
+    Puppet::Type.newtype(:test_resource) do
+      newparam(:name, :namevar => true)
+      newparam(:log_file)
+    end
+  end
+
+  describe '#request' do
+    let(:resource_attrs) do
+      {
+        :name => 'stubresource',
+      }
+    end
+
+    let(:provider) do
+      Puppet::Provider::Openstack.new(type.new(resource_attrs))
+    end
+
+    it 'makes a successful request' do
+      provider.class.stubs(:openstack)
+                    .with('project', 'list', '--quiet', '--format', 'csv', ['--long'])
+                    .returns('"ID","Name","Description","Enabled"
+"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True
+')
+      response = Puppet::Provider::Openstack.request('project', 'list', ['--long'])
+      expect(response.first[:description]).to eq("Test tenant")
+    end
+
+    context 'on connection errors' do
+      it 'retries' do
+        ENV['OS_USERNAME']     = 'test'
+        ENV['OS_PASSWORD']     = 'abc123'
+        ENV['OS_PROJECT_NAME'] = 'test'
+        ENV['OS_AUTH_URL']     = 'http://127.0.0.1:5000'
+        provider.class.stubs(:openstack)
+                      .with('project', 'list', '--quiet', '--format', 'csv', ['--long'])
+                      .raises(Puppet::ExecutionFailure, 'Unable to establish connection')
+                      .then
+                      .returns('')
+        provider.class.expects(:sleep).with(2).returns(nil)
+        Puppet::Provider::Openstack.request('project', 'list', ['--long'])
+      end
+    end
+  end
+
+  describe 'parse_csv' do
+    context 'with mixed stderr' do
+      text = "ERROR: Testing\n\"field\",\"test\",1,2,3\n"
+      csv = Puppet::Provider::Openstack.parse_csv(text)
+      it 'should ignore non-CSV text at the beginning of the input' do
+        expect(csv).to be_kind_of(Array)
+        expect(csv[0]).to match_array(['field', 'test', '1', '2', '3'])
+        expect(csv.size).to eq(1)
+      end
+    end
+
+    context 'with \r\n line endings' do
+      text = "ERROR: Testing\r\n\"field\",\"test\",1,2,3\r\n"
+      csv = Puppet::Provider::Openstack.parse_csv(text)
+      it 'ignore the carriage returns' do
+        expect(csv).to be_kind_of(Array)
+        expect(csv[0]).to match_array(['field', 'test', '1', '2', '3'])
+        expect(csv.size).to eq(1)
+      end
+    end
+
+    context 'with embedded newlines' do
+      text = "ERROR: Testing\n\"field\",\"te\nst\",1,2,3\n"
+      csv = Puppet::Provider::Openstack.parse_csv(text)
+      it 'should parse correctly' do
+        expect(csv).to be_kind_of(Array)
+        expect(csv[0]).to match_array(['field', "te\nst", '1', '2', '3'])
+        expect(csv.size).to eq(1)
+      end
+    end
+  end
+end