Add openstacklib module
master bcbe7aa35c03c83dd58842fdb0f72a332e660124 source: https://github.com/stackforge/puppet-openstacklib Partially Implements: blueprint upgrade-openstack-puppet-modules Change-Id: I6eea00337c5cce2269c236b49305ba7085f68eb4
This commit is contained in:
parent
e494cabc57
commit
d3a5608583
12
deployment/puppet/openstacklib/.fixtures.yml
Normal file
12
deployment/puppet/openstacklib/.fixtures.yml
Normal file
@ -0,0 +1,12 @@
|
||||
fixtures:
|
||||
repositories:
|
||||
apache: git://github.com/puppetlabs/puppetlabs-apache.git
|
||||
concat:
|
||||
repo: 'git://github.com/puppetlabs/puppetlabs-concat.git'
|
||||
ref: '1.2.1'
|
||||
mysql: git://github.com/puppetlabs/puppetlabs-mysql.git
|
||||
postgresql: git://github.com/puppetlabs/puppetlabs-postgresql.git
|
||||
stdlib: git://github.com/puppetlabs/puppetlabs-stdlib.git
|
||||
rabbitmq: 'git://github.com/puppetlabs/puppetlabs-rabbitmq'
|
||||
symlinks:
|
||||
'openstacklib': "#{source_dir}"
|
4
deployment/puppet/openstacklib/.gitignore
vendored
Normal file
4
deployment/puppet/openstacklib/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
*.swp
|
||||
spec/fixtures/*
|
||||
pkg
|
||||
Gemfile.lock
|
31
deployment/puppet/openstacklib/Gemfile
Normal file
31
deployment/puppet/openstacklib/Gemfile
Normal file
@ -0,0 +1,31 @@
|
||||
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-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'
|
||||
end
|
||||
|
||||
if puppetversion = ENV['PUPPET_GEM_VERSION']
|
||||
gem 'puppet', puppetversion, :require => false
|
||||
else
|
||||
gem 'puppet', :require => false
|
||||
end
|
||||
|
||||
# vim:ft=ruby
|
13
deployment/puppet/openstacklib/LICENSE
Normal file
13
deployment/puppet/openstacklib/LICENSE
Normal file
@ -0,0 +1,13 @@
|
||||
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.
|
||||
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.
|
341
deployment/puppet/openstacklib/README.md
Normal file
341
deployment/puppet/openstacklib/README.md
Normal file
@ -0,0 +1,341 @@
|
||||
openstacklib
|
||||
============
|
||||
|
||||
5.1.0 - 2014.2 - Juno
|
||||
#### Table of Contents
|
||||
|
||||
1. [Overview - What is the openstacklib module?](#overview)
|
||||
2. [Module Description - What does the module do?](#module-description)
|
||||
3. [Setup - The basics of getting started with openstacklib](#setup)
|
||||
4. [Implementation - An under-the-hood peek at what the module is doing](#implementation)
|
||||
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 openstacklib module is a part of [Stackforge](https://github.com/stackforge),
|
||||
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 itself is used to expose common functionality
|
||||
between Openstack modules as a library that can be utilized to avoid code
|
||||
duplication.
|
||||
|
||||
Module Description
|
||||
------------------
|
||||
|
||||
The openstacklib module is a library module for other Openstack modules to
|
||||
utilize. A thorough description will be added later.
|
||||
|
||||
This module is tested in combination with other modules needed to build and
|
||||
leverage an entire Openstack software stack. These modules can be found, all
|
||||
pulled together in the [openstack module](https://github.com/stackforge/puppet-openstack).
|
||||
|
||||
Setup
|
||||
-----
|
||||
|
||||
### Installing openstacklib
|
||||
|
||||
example% puppet module install puppetlabs/openstacklib
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
### Classes and Defined Types
|
||||
|
||||
#### Defined type: openstacklib::db::mysql
|
||||
|
||||
The db::mysql resource is a library resource that can be used by nova, cinder,
|
||||
ceilometer, etc., to create a mysql database with configurable privileges for
|
||||
a user connecting from defined hosts.
|
||||
|
||||
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::mysql you might declare:
|
||||
|
||||
```
|
||||
::openstacklib::db::mysql { 'heat':
|
||||
password_hash => mysql_password($password),
|
||||
dbname => $dbname,
|
||||
user => $user,
|
||||
host => $host,
|
||||
charset => $charset,
|
||||
collate => $collate,
|
||||
allowed_hosts => $allowed_hosts,
|
||||
notify => Exec['heat-dbsync'],
|
||||
}
|
||||
```
|
||||
|
||||
Some modules should ensure that the database is created before the service is
|
||||
set up. For example, in keystone::db::mysql you would have:
|
||||
|
||||
```
|
||||
::openstacklib::db::mysql { 'keystone':
|
||||
password_hash => mysql_password($password),
|
||||
dbname => $dbname,
|
||||
user => $user,
|
||||
host => $host,
|
||||
charset => $charset,
|
||||
collate => $collate,
|
||||
allowed_hosts => $allowed_hosts,
|
||||
notify => Exec['keystone-manage db_sync'],
|
||||
before => Service['keystone'],
|
||||
}
|
||||
```
|
||||
|
||||
** Parameters for openstacklib::db::mysql: **
|
||||
|
||||
#####`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'
|
||||
|
||||
#####`host`
|
||||
The IP address or hostname of the user in mysql_grant;
|
||||
string; optional; default to '127.0.0.1'
|
||||
|
||||
#####`charset`
|
||||
The charset to use for the database;
|
||||
string; optional; default to 'utf8'
|
||||
|
||||
#####`collate`
|
||||
The collate to use for the database;
|
||||
string; optional; default to 'utf8_general_ci'
|
||||
|
||||
#####`allowed_hosts`
|
||||
Additional hosts that are allowed to access this database;
|
||||
array or string; optional; default to undef
|
||||
|
||||
#####`privileges`
|
||||
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
|
||||
|
||||
The service_validation resource is a library resource that can be used by nova, cinder,
|
||||
ceilometer, etc., to validate that a resource is actually up and running.
|
||||
|
||||
For example, in nova::api you might declare:
|
||||
|
||||
```
|
||||
::openstacklib::service_validation { 'nova-api':
|
||||
command => 'nova list',
|
||||
}
|
||||
```
|
||||
This defined resource creates an exec-anchor pair where the anchor depends upon
|
||||
the successful exec run.
|
||||
|
||||
** Parameters for openstacklib::service_validation: **
|
||||
|
||||
#####`command`
|
||||
Command to run for validating the service;
|
||||
string; required
|
||||
|
||||
#####`service_name`
|
||||
The name of the service to validate;
|
||||
string; optional; default to the $title of the resource, i.e. 'nova-api'
|
||||
|
||||
#####`path`
|
||||
The path of the command to validate the service;
|
||||
string; optional; default to '/usr/bin:/bin:/usr/sbin:/sbin'
|
||||
|
||||
#####`provider`
|
||||
The provider to use for the exec command;
|
||||
string; optional; default to 'shell'
|
||||
|
||||
#####`tries`
|
||||
Number of times to retry validation;
|
||||
string; optional; default to '10'
|
||||
|
||||
#####`try_sleep`
|
||||
Number of seconds between validation attempts;
|
||||
string; optional; default to '2'
|
||||
|
||||
### Types and Providers
|
||||
|
||||
#### Aviator
|
||||
|
||||
#####`Puppet::add_aviator_params`
|
||||
|
||||
The aviator type is not a real type, but it serves to simulate a mixin model,
|
||||
whereby other types can call out to the Puppet::add\_aviator\_params method in
|
||||
order to add aviator-specific parameters to themselves. Currently this adds the
|
||||
auth parameter to the given type. The method must be called after the type is
|
||||
declared, e.g.:
|
||||
|
||||
```puppet
|
||||
require 'puppet/type/aviator'
|
||||
Puppet::Type.newtype(:my_type) do
|
||||
# ...
|
||||
end
|
||||
Puppet::add_aviator_params(:my_type)
|
||||
```
|
||||
|
||||
#####`Puppet::Provider::Aviator`
|
||||
|
||||
The aviator provider is a parent provider intended to serve as a base for other
|
||||
providers that need to authenticate against keystone in order to accomplish a
|
||||
task.
|
||||
|
||||
**`Puppet::Provider::Aviator#authenticate`**
|
||||
|
||||
Either creates an authenticated session or sets up an unauthenticated session
|
||||
with instance variables initialized with a token to inject into the next request.
|
||||
It takes as arguments a set of authentication parameters as a hash and a path
|
||||
to a log file. Puppet::Provider::Aviator#authencate looks for five different
|
||||
possible methods of authenticating, in the following order:
|
||||
|
||||
1) Username and password credentials in the auth parameters
|
||||
2) The path to an openrc file containing credentials to read in the auth
|
||||
parameters
|
||||
3) A service token in the auth parameters
|
||||
4) Environment variables set for the environment in which Puppet is running
|
||||
5) A service token in /etc/keystone/keystone.conf. This option provides
|
||||
backwards compatibility with earlier keystone providers.
|
||||
|
||||
If the provider has password credentials, it can create an authenticated
|
||||
session. If it only has a service token, it initializes an unauthenciated
|
||||
session and a hash of session data that can be injected into a future request.
|
||||
|
||||
**`Puppet::Provider::Aviator#make_request`**
|
||||
|
||||
After creating a session, the make\_request method provides an interface that
|
||||
providers can use to make requests without worrying about whether they have an
|
||||
authenticated or unauthenticated session. It takes as arguments the
|
||||
Aviator::Service it is making a request at (for example, keystone), a symbol for
|
||||
the request (for example, :list\_tenants), and optionally a block to execute
|
||||
that will set parameters for an update request.
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
### openstacklib
|
||||
|
||||
openstacklib is a combination of Puppet manifest and ruby code to delivery
|
||||
configuration and extra functionality through types and providers.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
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
|
||||
-----------
|
||||
|
||||
Developer documentation for the entire puppet-openstack project.
|
||||
|
||||
* https://wiki.openstack.org/wiki/Puppet-openstack#Developer_documentation
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* https://github.com/stackforge/puppet-openstacklib/graphs/contributors
|
||||
|
||||
Versioning
|
||||
----------
|
||||
|
||||
This module has been given version 5 to track the puppet-openstack modules. The
|
||||
versioning for the puppet-openstack modules are as follows:
|
||||
|
||||
```
|
||||
Puppet Module :: OpenStack Version :: OpenStack Codename
|
||||
2.0.0 -> 2013.1.0 -> Grizzly
|
||||
3.0.0 -> 2013.2.0 -> Havana
|
||||
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.
|
7
deployment/puppet/openstacklib/Rakefile
Normal file
7
deployment/puppet/openstacklib/Rakefile
Normal file
@ -0,0 +1,7 @@
|
||||
require 'rubygems'
|
||||
require 'puppetlabs_spec_helper/rake_tasks'
|
||||
require 'puppet-lint/tasks/puppet-lint'
|
||||
|
||||
PuppetLint.configuration.fail_on_warnings = true
|
||||
PuppetLint.configuration.send('disable_80chars')
|
||||
PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"]
|
@ -0,0 +1,72 @@
|
||||
require 'puppet/parser/functions'
|
||||
|
||||
Puppet::Parser::Functions.newfunction(:os_database_connection,
|
||||
:type => :rvalue,
|
||||
:doc => <<-EOS
|
||||
This function builds a os_database_connection string from various parameters.
|
||||
EOS
|
||||
) do |arguments|
|
||||
|
||||
require 'uri'
|
||||
|
||||
if (arguments.size != 1) then
|
||||
raise(Puppet::ParseError, "os_database_connection(): Wrong number of arguments " +
|
||||
"given (#{arguments.size} for 1)")
|
||||
end
|
||||
|
||||
v = arguments[0]
|
||||
klass = v.class
|
||||
|
||||
unless klass == Hash
|
||||
raise(Puppet::ParseError, "os_database_connection(): Requires an hash, got #{klass}")
|
||||
end
|
||||
|
||||
v.keys.each do |key|
|
||||
unless (v[key].class == String) or (v[key] == :undef)
|
||||
raise(Puppet::ParseError, "os_database_connection(): #{key} should be a String")
|
||||
end
|
||||
end
|
||||
|
||||
parts = {}
|
||||
|
||||
unless v.include?('dialect')
|
||||
raise(Puppet::ParseError, 'os_database_connection(): dialect is required')
|
||||
end
|
||||
|
||||
if v.include?('host')
|
||||
parts[:host] = v['host']
|
||||
end
|
||||
|
||||
unless v.include?('database')
|
||||
raise(Puppet::ParseError, 'os_database_connection(): database is required')
|
||||
end
|
||||
|
||||
if v.include?('port')
|
||||
if v.include?('host')
|
||||
parts[:port] = v['port'].to_i
|
||||
else
|
||||
raise(Puppet::ParseError, 'os_database_connection(): host is required with port')
|
||||
end
|
||||
end
|
||||
|
||||
if v.include?('username') and (v['username'] != :undef) and (v['username'].to_s != '')
|
||||
parts[:userinfo] = URI.escape(v['username'])
|
||||
if v.include?('password') and (v['password'] != :undef) and (v['password'].to_s != '')
|
||||
parts[:userinfo] += ":#{URI.escape(v['password'])}"
|
||||
end
|
||||
end
|
||||
|
||||
if v.include?('charset')
|
||||
parts[:query] = "charset=#{v['charset']}"
|
||||
end
|
||||
|
||||
parts[:scheme] = v['dialect']
|
||||
|
||||
if v.include?('host')
|
||||
parts[:path] = "/#{v['database']}"
|
||||
else
|
||||
parts[:path] = "///#{v['database']}"
|
||||
end
|
||||
|
||||
URI::Generic.build(parts).to_s
|
||||
end
|
@ -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
|
@ -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
|
@ -0,0 +1,89 @@
|
||||
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
|
||||
list = KEYS.delete_if { |key, val| key == :identity_api_version }
|
||||
list.each { |key, val| self.set(key, '') if self.class.defined?("@#{key}".to_sym) }
|
||||
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
|
68
deployment/puppet/openstacklib/manifests/db/mysql.pp
Normal file
68
deployment/puppet/openstacklib/manifests/db/mysql.pp
Normal file
@ -0,0 +1,68 @@
|
||||
# == Definition: openstacklib::db::mysql
|
||||
#
|
||||
# This resource configures a mysql 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'
|
||||
#
|
||||
# [*host*]
|
||||
# The IP address or hostname of the user in mysql_grant;
|
||||
# string; optional; default to '127.0.0.1'
|
||||
#
|
||||
# [*charset*]
|
||||
# The charset to use for the database;
|
||||
# string; optional; default to 'utf8'
|
||||
#
|
||||
# [*collate*]
|
||||
# The collate to use for the database;
|
||||
# string; optional; default to 'utf8_general_ci'
|
||||
#
|
||||
# [*allowed_hosts*]
|
||||
# Additional hosts that are allowed to access this database;
|
||||
# array or string; optional; default to undef
|
||||
#
|
||||
# [*privileges*]
|
||||
# Privileges given to the database user;
|
||||
# string or array of strings; optional; default to 'ALL'
|
||||
|
||||
define openstacklib::db::mysql (
|
||||
$password_hash,
|
||||
$dbname = $title,
|
||||
$user = $title,
|
||||
$host = '127.0.0.1',
|
||||
$charset = 'utf8',
|
||||
$collate = 'utf8_general_ci',
|
||||
$allowed_hosts = [],
|
||||
$privileges = 'ALL',
|
||||
) {
|
||||
|
||||
include ::mysql::client
|
||||
|
||||
mysql_database { $dbname:
|
||||
ensure => present,
|
||||
charset => $charset,
|
||||
collate => $collate,
|
||||
require => [ Class['mysql::server'], Class['mysql::client'] ],
|
||||
}
|
||||
|
||||
$allowed_hosts_list = unique(concat(any2array($allowed_hosts), [$host]))
|
||||
$real_allowed_hosts = prefix($allowed_hosts_list, "${dbname}_")
|
||||
|
||||
openstacklib::db::mysql::host_access { $real_allowed_hosts:
|
||||
user => $user,
|
||||
password_hash => $password_hash,
|
||||
database => $dbname,
|
||||
privileges => $privileges,
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
# Allow a user to access the database for the service
|
||||
#
|
||||
# == Namevar
|
||||
# String with the form dbname_host. The host part of the string is the host
|
||||
# to allow
|
||||
#
|
||||
# == Parameters
|
||||
# [*user*]
|
||||
# username to allow
|
||||
#
|
||||
# [*password_hash*]
|
||||
# user password hash
|
||||
#
|
||||
# [*database*]
|
||||
# the database name
|
||||
#
|
||||
# [*privileges*]
|
||||
# the privileges to grant to this user
|
||||
#
|
||||
define openstacklib::db::mysql::host_access (
|
||||
$user,
|
||||
$password_hash,
|
||||
$database,
|
||||
$privileges,
|
||||
) {
|
||||
validate_re($title, '_', 'Title must be $dbname_$host')
|
||||
|
||||
$host = inline_template('<%= @title.split("_").last %>')
|
||||
|
||||
mysql_user { "${user}@${host}":
|
||||
password_hash => $password_hash,
|
||||
require => Mysql_database[$database],
|
||||
}
|
||||
|
||||
mysql_grant { "${user}@${host}/${database}.*":
|
||||
privileges => $privileges,
|
||||
table => "${database}.*",
|
||||
require => Mysql_user["${user}@${host}"],
|
||||
user => "${user}@${host}",
|
||||
}
|
||||
}
|
46
deployment/puppet/openstacklib/manifests/db/postgresql.pp
Normal file
46
deployment/puppet/openstacklib/manifests/db/postgresql.pp
Normal file
@ -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,
|
||||
}
|
||||
}
|
105
deployment/puppet/openstacklib/manifests/messaging/rabbitmq.pp
Normal file
105
deployment/puppet/openstacklib/manifests/messaging/rabbitmq.pp
Normal file
@ -0,0 +1,105 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# == Definition: openstacklib::messaging::rabbitmq
|
||||
#
|
||||
# This resource creates RabbitMQ resources for an OpenStack service.
|
||||
#
|
||||
# == Parameters:
|
||||
#
|
||||
# [*userid*]
|
||||
# (optional) The username to use when connecting to Rabbit
|
||||
# Defaults to 'guest'
|
||||
#
|
||||
# [*password*]
|
||||
# (optional) The password to use when connecting to Rabbit
|
||||
# Defaults to 'guest'
|
||||
#
|
||||
# [*virtual_host*]
|
||||
# (optional) The virtual host to use when connecting to Rabbit
|
||||
# Defaults to '/'
|
||||
#
|
||||
# [*is_admin*]
|
||||
# (optional) If the user should be admin or not
|
||||
# Defaults to false
|
||||
#
|
||||
# [*configure_permission*]
|
||||
# (optional) Define configure permission
|
||||
# Defaults to '.*'
|
||||
#
|
||||
# [*write_permission*]
|
||||
# (optional) Define write permission
|
||||
# Defaults to '.*'
|
||||
#
|
||||
# [*read_permission*]
|
||||
# (optional) Define read permission
|
||||
# Defaults to '.*'
|
||||
#
|
||||
# [*manage_user*]
|
||||
# (optional) Manage or not the user
|
||||
# Defaults to true
|
||||
#
|
||||
# [*manage_user_permissions*]
|
||||
# (optional) Manage or not user permissions
|
||||
# Defaults to true
|
||||
#
|
||||
# [*manage_vhost*]
|
||||
# (optional) Manage or not the vhost
|
||||
# Defaults to true
|
||||
#
|
||||
define openstacklib::messaging::rabbitmq(
|
||||
$userid = 'guest',
|
||||
$password = 'guest',
|
||||
$virtual_host = '/',
|
||||
$is_admin = false,
|
||||
$configure_permission = '.*',
|
||||
$write_permission = '.*',
|
||||
$read_permission = '.*',
|
||||
$manage_user = true,
|
||||
$manage_user_permissions = true,
|
||||
$manage_vhost = true,
|
||||
) {
|
||||
|
||||
if $manage_user {
|
||||
if $userid == 'guest' {
|
||||
$is_admin_real = false
|
||||
} else {
|
||||
$is_admin_real = $is_admin
|
||||
}
|
||||
ensure_resource('rabbitmq_user', $userid, {
|
||||
'admin' => $is_admin_real,
|
||||
'password' => $password,
|
||||
'provider' => 'rabbitmqctl',
|
||||
})
|
||||
}
|
||||
|
||||
if $manage_user_permissions {
|
||||
ensure_resource('rabbitmq_user_permissions', "${userid}@${virtual_host}", {
|
||||
'configure_permission' => $configure_permission,
|
||||
'write_permission' => $write_permission,
|
||||
'read_permission' => $read_permission,
|
||||
'provider' => 'rabbitmqctl',
|
||||
})
|
||||
}
|
||||
|
||||
if $manage_vhost {
|
||||
ensure_resource('rabbitmq_vhost', $virtual_host, {
|
||||
'provider' => 'rabbitmqctl',
|
||||
})
|
||||
}
|
||||
|
||||
}
|
18
deployment/puppet/openstacklib/manifests/openstackclient.pp
Normal file
18
deployment/puppet/openstacklib/manifests/openstackclient.pp
Normal file
@ -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',
|
||||
}
|
||||
}
|
19
deployment/puppet/openstacklib/manifests/policy.pp
Normal file
19
deployment/puppet/openstacklib/manifests/policy.pp
Normal file
@ -0,0 +1,19 @@
|
||||
# == Class: openstacklib::policies
|
||||
#
|
||||
# This resource is an helper to call the policy definition
|
||||
#
|
||||
# == Parameters:
|
||||
#
|
||||
# [*policies*]
|
||||
# Hash of policies one would like to set to specific values
|
||||
# hash; optional
|
||||
#
|
||||
class openstacklib::policy (
|
||||
$policies = {},
|
||||
) {
|
||||
|
||||
validate_hash($policies)
|
||||
|
||||
create_resources('openstacklib::policy::base', $policies)
|
||||
|
||||
}
|
45
deployment/puppet/openstacklib/manifests/policy/base.pp
Normal file
45
deployment/puppet/openstacklib/manifests/policy/base.pp
Normal file
@ -0,0 +1,45 @@
|
||||
# == Definition: openstacklib::policy::base
|
||||
#
|
||||
# This resource configures the policy.json file for an OpenStack service
|
||||
#
|
||||
# == Parameters:
|
||||
#
|
||||
# [*file_path*]
|
||||
# Path to the policy.json file
|
||||
# string; required
|
||||
#
|
||||
# [*key*]
|
||||
# The key to replace the value for
|
||||
# string; required; the key to replace the value for
|
||||
#
|
||||
# [*value*]
|
||||
# The value to set
|
||||
# string; optional; the value to set
|
||||
#
|
||||
define openstacklib::policy::base (
|
||||
$file_path,
|
||||
$key,
|
||||
$value = '',
|
||||
) {
|
||||
|
||||
# Add entry if it doesn't exists
|
||||
augeas { "${file_path}-${key}-${value}-add":
|
||||
lens => 'Json.lns',
|
||||
incl => $file_path,
|
||||
changes => [
|
||||
"set dict/entry[last()+1] \"${key}\"",
|
||||
"set dict/entry[last()]/string \"${value}\"",
|
||||
],
|
||||
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"],
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,69 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# == Definition: openstacklib::service_validation
|
||||
#
|
||||
# This resource does service validation for an OpenStack service.
|
||||
#
|
||||
# == Parameters:
|
||||
#
|
||||
# [*command*]
|
||||
# Command to run for validating the service;
|
||||
# string; required
|
||||
#
|
||||
# [*service_name*]
|
||||
# The name of the service to validate;
|
||||
# string; optional; default to the $title of the resource, i.e. 'nova-api'
|
||||
#
|
||||
# [*path*]
|
||||
# The path of the command to validate the service;
|
||||
# string; optional; default to '/usr/bin:/bin:/usr/sbin:/sbin'
|
||||
#
|
||||
# [*provider*]
|
||||
# The provider to use for the exec command;
|
||||
# string; optional; default to 'shell'
|
||||
#
|
||||
# [*tries*]
|
||||
# Number of times to retry validation;
|
||||
# string; optional; default to '10'
|
||||
#
|
||||
# [*try_sleep*]
|
||||
# Number of seconds between validation attempts;
|
||||
# string; optional; default to '2'
|
||||
#
|
||||
define openstacklib::service_validation(
|
||||
$command,
|
||||
$service_name = $name,
|
||||
$path = '/usr/bin:/bin:/usr/sbin:/sbin',
|
||||
$provider = shell,
|
||||
$tries = '10',
|
||||
$try_sleep = '2',
|
||||
) {
|
||||
|
||||
exec { "execute ${service_name} validation":
|
||||
path => $path,
|
||||
provider => $provider,
|
||||
command => $command,
|
||||
tries => $tries,
|
||||
try_sleep => $try_sleep,
|
||||
}
|
||||
|
||||
anchor { "create ${service_name} anchor":
|
||||
require => Exec["execute ${service_name} validation"],
|
||||
}
|
||||
|
||||
}
|
204
deployment/puppet/openstacklib/manifests/wsgi/apache.pp
Normal file
204
deployment/puppet/openstacklib/manifests/wsgi/apache.pp
Normal file
@ -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],
|
||||
}
|
||||
|
||||
}
|
40
deployment/puppet/openstacklib/metadata.json
Normal file
40
deployment/puppet/openstacklib/metadata.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "stackforge-openstacklib",
|
||||
"version": "5.1.0",
|
||||
"author": "Puppet Labs and OpenStack Contributors",
|
||||
"summary": "Puppet OpenStack Libraries",
|
||||
"license": "Apache-2.0",
|
||||
"source": "git://github.com/openstack/puppet-openstacklib.git",
|
||||
"project_page": "https://launchpad.net/puppet-openstacklib",
|
||||
"issues_url": "https://bugs.launchpad.net/puppet-openstacklib",
|
||||
"requirements": [
|
||||
{ "name": "pe","version_requirement": "3.x" },
|
||||
{ "name": "puppet","version_requirement": "3.x" }
|
||||
],
|
||||
"operatingsystem_support": [
|
||||
{
|
||||
"operatingsystem": "Debian",
|
||||
"operatingsystemrelease": ["7"]
|
||||
},
|
||||
{
|
||||
"operatingsystem": "Fedora",
|
||||
"operatingsystemrelease": ["20"]
|
||||
},
|
||||
{
|
||||
"operatingsystem": "RedHat",
|
||||
"operatingsystemrelease": ["6.5","7"]
|
||||
},
|
||||
{
|
||||
"operatingsystem": "Ubuntu",
|
||||
"operatingsystemrelease": ["12.04","14.04"]
|
||||
}
|
||||
],
|
||||
"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" }
|
||||
]
|
||||
}
|
35
deployment/puppet/openstacklib/spec/acceptance/mysql_spec.rb
Normal file
35
deployment/puppet/openstacklib/spec/acceptance/mysql_spec.rb
Normal file
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -0,0 +1,66 @@
|
||||
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,
|
||||
erlang_cookie => 'secrete',
|
||||
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
|
1
deployment/puppet/openstacklib/spec/classes/init_spec.rb
Normal file
1
deployment/puppet/openstacklib/spec/classes/init_spec.rb
Normal file
@ -0,0 +1 @@
|
||||
require 'spec_helper'
|
@ -0,0 +1,25 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'openstacklib::policy' do
|
||||
|
||||
let :params do
|
||||
{
|
||||
:policies => {
|
||||
'foo' => {
|
||||
'file_path' => '/etc/nova/policy.json',
|
||||
'key' => 'context_is_admin',
|
||||
'value' => 'foo:bar'
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'configures the proper policy' do
|
||||
is_expected.to contain_openstacklib__policy__base('foo').with(
|
||||
:file_path => '/etc/nova/policy.json',
|
||||
:key => 'context_is_admin',
|
||||
:value => 'foo:bar'
|
||||
)
|
||||
end
|
||||
|
||||
end
|
@ -0,0 +1,50 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'openstacklib::db::mysql::host_access' do
|
||||
|
||||
let :pre_condition do
|
||||
"include mysql::server\n" +
|
||||
"openstacklib::db::mysql { 'nova':\n" +
|
||||
" password_hash => 'AA1420F182E88B9E5F874F6FBE7459291E8F4601'}"
|
||||
end
|
||||
|
||||
shared_examples 'openstacklib::db::mysql::host_access examples' do
|
||||
|
||||
context 'with required parameters' do
|
||||
let (:title) { 'nova_10.0.0.1' }
|
||||
let :params do
|
||||
{ :user => 'foobar',
|
||||
:password_hash => 'AA1420F182E88B9E5F874F6FBE7459291E8F4601',
|
||||
:database => 'nova',
|
||||
:privileges => 'ALL' }
|
||||
end
|
||||
|
||||
it { is_expected.to contain_mysql_user("#{params[:user]}@10.0.0.1").with(
|
||||
:password_hash => params[:password_hash]
|
||||
)}
|
||||
|
||||
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]}.*"
|
||||
)}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'on a Debian osfamily' do
|
||||
let :facts do
|
||||
{ :osfamily => "Debian" }
|
||||
end
|
||||
|
||||
include_examples 'openstacklib::db::mysql::host_access examples'
|
||||
end
|
||||
|
||||
context 'on a RedHat osfamily' do
|
||||
let :facts do
|
||||
{ :osfamily => 'RedHat' }
|
||||
end
|
||||
|
||||
include_examples 'openstacklib::db::mysql::host_access examples'
|
||||
end
|
||||
end
|
@ -0,0 +1,163 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'openstacklib::db::mysql' do
|
||||
|
||||
let :pre_condition do
|
||||
'include mysql::server'
|
||||
end
|
||||
|
||||
let (:title) { 'nova' }
|
||||
|
||||
let :required_params do
|
||||
{ :password_hash => 'AA1420F182E88B9E5F874F6FBE7459291E8F4601' }
|
||||
end
|
||||
|
||||
shared_examples 'openstacklib::db::mysql examples' do
|
||||
|
||||
context 'with only required parameters' do
|
||||
let :params do
|
||||
required_params
|
||||
end
|
||||
|
||||
it { is_expected.to contain_mysql_database(title).with(
|
||||
:charset => 'utf8',
|
||||
:collate => 'utf8_general_ci'
|
||||
)}
|
||||
it { is_expected.to contain_openstacklib__db__mysql__host_access("#{title}_127.0.0.1").with(
|
||||
:user => title,
|
||||
:database => title,
|
||||
:privileges => 'ALL'
|
||||
)}
|
||||
end
|
||||
|
||||
context 'with overriding dbname parameter' do
|
||||
let :params do
|
||||
{ :dbname => 'foobar' }.merge(required_params)
|
||||
end
|
||||
|
||||
it { is_expected.to contain_mysql_database(params[:dbname]).with(
|
||||
:charset => 'utf8',
|
||||
:collate => 'utf8_general_ci'
|
||||
)}
|
||||
it { is_expected.to contain_openstacklib__db__mysql__host_access("#{params[:dbname]}_127.0.0.1").with(
|
||||
:user => title,
|
||||
:database => params[:dbname],
|
||||
:privileges => 'ALL'
|
||||
)}
|
||||
end
|
||||
|
||||
context 'with overriding user parameter' do
|
||||
let :params do
|
||||
{ :user => 'foobar' }.merge(required_params)
|
||||
end
|
||||
|
||||
it { is_expected.to contain_mysql_database(title).with(
|
||||
:charset => 'utf8',
|
||||
:collate => 'utf8_general_ci'
|
||||
)}
|
||||
it { is_expected.to contain_openstacklib__db__mysql__host_access("#{title}_127.0.0.1").with(
|
||||
:user => params[:user],
|
||||
:database => title,
|
||||
:privileges => 'ALL',
|
||||
)}
|
||||
end
|
||||
|
||||
context 'when overriding charset parameter' do
|
||||
let :params do
|
||||
{ :charset => 'latin1' }.merge(required_params)
|
||||
end
|
||||
|
||||
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 { 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::Mysql[#{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::Mysql[keystone]") }
|
||||
end
|
||||
|
||||
context "overriding allowed_hosts parameter with array value" do
|
||||
let :params do
|
||||
{ :allowed_hosts => ['127.0.0.1','%'] }.merge(required_params)
|
||||
end
|
||||
|
||||
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 {is_expected.to contain_openstacklib__db__mysql__host_access("#{title}_%").with(
|
||||
:user => title,
|
||||
:password_hash => params[:password_hash],
|
||||
:database => title
|
||||
)}
|
||||
end
|
||||
|
||||
context "overriding allowed_hosts parameter with string value" do
|
||||
let :params do
|
||||
{ :allowed_hosts => '192.168.1.1' }.merge(required_params)
|
||||
end
|
||||
|
||||
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
|
||||
)}
|
||||
end
|
||||
|
||||
context "overriding allowed_hosts parameter equals to host param " do
|
||||
let :params do
|
||||
{ :allowed_hosts => '127.0.0.1' }.merge(required_params)
|
||||
end
|
||||
|
||||
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
|
||||
)}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'on a Debian osfamily' do
|
||||
let :facts do
|
||||
{ :osfamily => "Debian" }
|
||||
end
|
||||
|
||||
include_examples 'openstacklib::db::mysql examples'
|
||||
end
|
||||
|
||||
context 'on a RedHat osfamily' do
|
||||
let :facts do
|
||||
{ :osfamily => 'RedHat' }
|
||||
end
|
||||
|
||||
include_examples 'openstacklib::db::mysql examples'
|
||||
end
|
||||
end
|
@ -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
|
@ -0,0 +1,101 @@
|
||||
#
|
||||
# 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::messaging::rabbitmq' do
|
||||
|
||||
let (:title) { 'nova' }
|
||||
|
||||
shared_examples 'openstacklib::messaging::rabbitmq examples' do
|
||||
|
||||
let :params do
|
||||
{}
|
||||
end
|
||||
|
||||
context 'with default parameters' do
|
||||
it { is_expected.to contain_rabbitmq_user('guest').with(
|
||||
:admin => false,
|
||||
:password => 'guest',
|
||||
:provider => 'rabbitmqctl',
|
||||
)}
|
||||
it { is_expected.to contain_rabbitmq_user_permissions('guest@/').with(
|
||||
:configure_permission => '.*',
|
||||
:write_permission => '.*',
|
||||
:read_permission => '.*',
|
||||
:provider => 'rabbitmqctl',
|
||||
)}
|
||||
it { is_expected.to contain_rabbitmq_vhost('/').with(
|
||||
:provider => 'rabbitmqctl',
|
||||
)}
|
||||
end
|
||||
|
||||
context 'with custom parameters' do
|
||||
before :each do
|
||||
params.merge!(
|
||||
:userid => 'nova',
|
||||
:password => 'secrete',
|
||||
:virtual_host => '/nova',
|
||||
:is_admin => true,
|
||||
:configure_permission => '.nova',
|
||||
:write_permission => '.nova',
|
||||
:read_permission => '.nova'
|
||||
)
|
||||
end
|
||||
|
||||
it { is_expected.to contain_rabbitmq_user('nova').with(
|
||||
:admin => true,
|
||||
:password => 'secrete',
|
||||
:provider => 'rabbitmqctl',
|
||||
)}
|
||||
it { is_expected.to contain_rabbitmq_user_permissions('nova@/nova').with(
|
||||
:configure_permission => '.nova',
|
||||
:write_permission => '.nova',
|
||||
:read_permission => '.nova',
|
||||
:provider => 'rabbitmqctl',
|
||||
)}
|
||||
it { is_expected.to contain_rabbitmq_vhost('/nova').with(
|
||||
:provider => 'rabbitmqctl',
|
||||
)}
|
||||
end
|
||||
|
||||
context 'when disabling vhost management' do
|
||||
before :each do
|
||||
params.merge!( :manage_vhost => false )
|
||||
end
|
||||
|
||||
it { is_expected.not_to contain_rabbitmq_vhost }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'on a Debian osfamily' do
|
||||
let :facts do
|
||||
{ :osfamily => "Debian" }
|
||||
end
|
||||
|
||||
include_examples 'openstacklib::messaging::rabbitmq examples'
|
||||
end
|
||||
|
||||
context 'on a RedHat osfamily' do
|
||||
let :facts do
|
||||
{ :osfamily => 'RedHat' }
|
||||
end
|
||||
|
||||
include_examples 'openstacklib::messaging::rabbitmq examples'
|
||||
end
|
||||
end
|
@ -0,0 +1,37 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'openstacklib::policy::base' do
|
||||
|
||||
let :title do
|
||||
'nova-contest_is_admin'
|
||||
end
|
||||
|
||||
let :params do
|
||||
{:file_path => '/etc/nova/policy.json',
|
||||
:key => 'context_is_admin or owner',
|
||||
:value => 'foo:bar'}
|
||||
end
|
||||
|
||||
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 or owner"]/string "foo:bar"',
|
||||
'require' => 'Augeas[/etc/nova/policy.json-context_is_admin or owner-foo:bar-add]'
|
||||
)
|
||||
end
|
||||
|
||||
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 or owner"',
|
||||
'set dict/entry[last()]/string "foo:bar"'
|
||||
],
|
||||
'onlyif' => 'match dict/entry[*][.="context_is_admin or owner"] size == 0'
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -0,0 +1,73 @@
|
||||
#
|
||||
# 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::service_validation' do
|
||||
|
||||
let (:title) { 'nova-api' }
|
||||
|
||||
let :required_params do
|
||||
{ :command => 'nova list' }
|
||||
end
|
||||
|
||||
shared_examples 'openstacklib::service_validation examples' do
|
||||
|
||||
context 'with only required parameters' do
|
||||
let :params do
|
||||
required_params
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exec("execute #{title} validation").with(
|
||||
:path => '/usr/bin:/bin:/usr/sbin:/sbin',
|
||||
:provider => 'shell',
|
||||
:command => 'nova list',
|
||||
:tries => '10',
|
||||
:try_sleep => '2',
|
||||
)}
|
||||
|
||||
it { is_expected.to contain_anchor("create #{title} anchor").with(
|
||||
:require => "Exec[execute #{title} validation]",
|
||||
)}
|
||||
|
||||
end
|
||||
|
||||
context 'when omitting a required parameter command' do
|
||||
let :params do
|
||||
required_params.delete(:command)
|
||||
end
|
||||
it { expect { is_expected.to raise_error(Puppet::Error) } }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'on a Debian osfamily' do
|
||||
let :facts do
|
||||
{ :osfamily => "Debian" }
|
||||
end
|
||||
|
||||
include_examples 'openstacklib::service_validation examples'
|
||||
end
|
||||
|
||||
context 'on a RedHat osfamily' do
|
||||
let :facts do
|
||||
{ :osfamily => 'RedHat' }
|
||||
end
|
||||
|
||||
include_examples 'openstacklib::service_validation examples'
|
||||
end
|
||||
end
|
@ -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
|
@ -0,0 +1,134 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'os_database_connection' do
|
||||
|
||||
it 'refuses String' do
|
||||
is_expected.to run.with_params('foo').\
|
||||
and_raise_error(Puppet::ParseError, /Requires an hash/)
|
||||
end
|
||||
|
||||
it 'refuses Array' do
|
||||
is_expected.to run.with_params(['foo']).\
|
||||
and_raise_error(Puppet::ParseError, /Requires an hash/)
|
||||
end
|
||||
|
||||
it 'refuses without at least one argument' do
|
||||
is_expected.to run.with_params().\
|
||||
and_raise_error(Puppet::ParseError, /Wrong number of arguments/)
|
||||
end
|
||||
|
||||
it 'refuses too many arguments' do
|
||||
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
|
||||
is_expected.to run.with_params({
|
||||
'dialect' => 'sqlite',
|
||||
'database' => '/var/lib/keystone/keystone.db',
|
||||
'port' => '3306',
|
||||
'charset' => 'utf-8'
|
||||
}).and_raise_error(Puppet::ParseError, /host is required with port/)
|
||||
end
|
||||
|
||||
context 'creates the correct connection URI' do
|
||||
|
||||
it 'with all parameters' do
|
||||
is_expected.to run.with_params({
|
||||
'dialect' => 'mysql',
|
||||
'host' => '127.0.0.1',
|
||||
'port' => '3306',
|
||||
'database' => 'test',
|
||||
'username' => 'guest',
|
||||
'password' => 's3cr3t',
|
||||
'charset' => 'utf-8'
|
||||
}).and_return('mysql://guest:s3cr3t@127.0.0.1:3306/test?charset=utf-8')
|
||||
end
|
||||
|
||||
it 'without port' do
|
||||
is_expected.to run.with_params({
|
||||
'dialect' => 'mysql',
|
||||
'host' => '127.0.0.1',
|
||||
'database' => 'test',
|
||||
'username' => 'guest',
|
||||
'password' => 's3cr3t',
|
||||
'charset' => 'utf-8'
|
||||
}).and_return('mysql://guest:s3cr3t@127.0.0.1/test?charset=utf-8')
|
||||
end
|
||||
|
||||
it 'without host and port' do
|
||||
is_expected.to run.with_params({
|
||||
'dialect' => 'sqlite',
|
||||
'database' => '/var/lib/keystone/keystone.db',
|
||||
'charset' => 'utf-8'
|
||||
}).and_return('sqlite:////var/lib/keystone/keystone.db?charset=utf-8')
|
||||
end
|
||||
|
||||
it 'without username and password' do
|
||||
is_expected.to run.with_params({
|
||||
'dialect' => 'mysql',
|
||||
'host' => '127.0.0.1',
|
||||
'port' => '3306',
|
||||
'database' => 'test',
|
||||
'charset' => 'utf-8'
|
||||
}).and_return('mysql://127.0.0.1:3306/test?charset=utf-8')
|
||||
end
|
||||
|
||||
it 'with username set to undef' do
|
||||
is_expected.to run.with_params({
|
||||
'dialect' => 'mysql',
|
||||
'host' => '127.0.0.1',
|
||||
'port' => '3306',
|
||||
'database' => 'test',
|
||||
'username' => :undef,
|
||||
'charset' => 'utf-8'
|
||||
}).and_return('mysql://127.0.0.1:3306/test?charset=utf-8')
|
||||
end
|
||||
|
||||
it 'with username set to an empty string' do
|
||||
is_expected.to run.with_params({
|
||||
'dialect' => 'mysql',
|
||||
'host' => '127.0.0.1',
|
||||
'port' => '3306',
|
||||
'database' => 'test',
|
||||
'username' => '',
|
||||
'charset' => 'utf-8'
|
||||
}).and_return('mysql://127.0.0.1:3306/test?charset=utf-8')
|
||||
end
|
||||
|
||||
it 'without password' do
|
||||
is_expected.to run.with_params({
|
||||
'dialect' => 'mysql',
|
||||
'host' => '127.0.0.1',
|
||||
'port' => '3306',
|
||||
'database' => 'test',
|
||||
'username' => 'guest',
|
||||
'charset' => 'utf-8'
|
||||
}).and_return('mysql://guest@127.0.0.1:3306/test?charset=utf-8')
|
||||
end
|
||||
|
||||
it 'with password set to undef' do
|
||||
is_expected.to run.with_params({
|
||||
'dialect' => 'mysql',
|
||||
'host' => '127.0.0.1',
|
||||
'port' => '3306',
|
||||
'database' => 'test',
|
||||
'username' => 'guest',
|
||||
'password' => :undef,
|
||||
'charset' => 'utf-8'
|
||||
}).and_return('mysql://guest@127.0.0.1:3306/test?charset=utf-8')
|
||||
end
|
||||
|
||||
it 'with password set to an empty string' do
|
||||
is_expected.to run.with_params({
|
||||
'dialect' => 'mysql',
|
||||
'host' => '127.0.0.1',
|
||||
'port' => '3306',
|
||||
'database' => 'test',
|
||||
'username' => 'guest',
|
||||
'password' => '',
|
||||
'charset' => 'utf-8'
|
||||
}).and_return('mysql://guest@127.0.0.1:3306/test?charset=utf-8')
|
||||
end
|
||||
end
|
||||
end
|
5
deployment/puppet/openstacklib/spec/shared_examples.rb
Normal file
5
deployment/puppet/openstacklib/spec/shared_examples.rb
Normal file
@ -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
|
7
deployment/puppet/openstacklib/spec/spec_helper.rb
Normal file
7
deployment/puppet/openstacklib/spec/spec_helper.rb
Normal file
@ -0,0 +1,7 @@
|
||||
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'
|
||||
end
|
@ -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
|
@ -0,0 +1,181 @@
|
||||
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'
|
||||
}
|
||||
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")
|
||||
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' })
|
||||
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")
|
||||
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' })
|
||||
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")
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a RC file containing user credentials' do
|
||||
it 'is successful' 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'"
|
||||
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")
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a RC file containing service token credentials' do
|
||||
it 'is successful' do
|
||||
mock = "export OS_TOKEN='test'\nexport OS_URL='abc123'\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")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,92 @@
|
||||
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 '#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
|
||||
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
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#set?' do
|
||||
context "without any credential" do
|
||||
it 'fails' do
|
||||
expect(creds.set?).to be_falsey
|
||||
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.auth_url).to eq("auth_url")
|
||||
expect(creds.password).to eq("password")
|
||||
expect(creds.project_name).to eq("project_name")
|
||||
expect(creds.username).to eq("username")
|
||||
expect(creds.token).to eq('token')
|
||||
expect(creds.url).to eq('url')
|
||||
expect(creds.identity_api_version).to eq('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
|
@ -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
|
Loading…
Reference in New Issue
Block a user