Implement openstacklib::wsgi::apache

Allow to serve a service with apache mod_wsgi like.
This code will be consummed by OpenStack project that allow to run a
service as a WSGI process.

Change-Id: Ib606df7d6ceec1db032c8e133598056878df0a01
This commit is contained in:
Emilien Macchi 2014-12-30 13:06:12 -05:00
parent 1a7531603b
commit 99bb19a0c4
6 changed files with 324 additions and 0 deletions

@ -1,6 +1,8 @@
fixtures:
repositories:
apache: git://github.com/puppetlabs/puppetlabs-apache.git
aviator: git://github.com/aimonb/puppet_aviator.git
concat: git://github.com/puppetlabs/puppetlabs-concat.git
mysql: git://github.com/puppetlabs/puppetlabs-mysql.git
postgresql: git://github.com/puppetlabs/puppetlabs-postgresql.git
stdlib: git://github.com/puppetlabs/puppetlabs-stdlib.git

189
manifests/wsgi/apache.pp Normal file

@ -0,0 +1,189 @@
#
# 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_script_path*]
# (optional) The path of the WSGI script.
# Defaults to undef
#
# [*wsgi_script_script*]
# (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_script_path = 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_path]) {
file { $wsgi_script_path:
ensure => directory,
owner => $user,
group => $group,
require => Package['httpd'],
}
}
file { "${service_name}_wsgi":
ensure => file,
path => "${wsgi_script_path}/${service_name}_wsgi",
source => $wsgi_script_source,
owner => $user,
group => $group,
mode => '0644',
require => File[$wsgi_script_path],
}
$wsgi_daemon_process_options = {
owner => $user,
group => $group,
processes => $workers,
threads => $threads,
}
$wsgi_script_aliases = hash([$path_real,$wsgi_script_path])
::apache::vhost { "${service_name}_wsgi":
ensure => 'present',
servername => $servername,
ip => $bind_host,
port => $bind_port,
docroot => $wsgi_script_path,
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 => $service_name,
wsgi_daemon_process_options => $wsgi_daemon_process_options,
wsgi_process_group => $service_name,
wsgi_script_aliases => $wsgi_script_aliases,
require => File["${service_name}_wsgi"],
}
}

@ -32,6 +32,7 @@
"description": "Puppet module library to expose common functionality between OpenStack modules.",
"dependencies": [
{ "name": "aimonb/aviator", "version_requirement": ">=0.4.2 <1.0.0" },
{ "name": "puppetlabs/apache", "version_requirement": ">=1.0.0 <2.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" },

@ -0,0 +1,120 @@
#
# 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' }
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_path => '/var/www/cgi-bin/keystone',
:wsgi_script_source => '/usr/share/keystone/keystone.wsgi'
}
end
shared_examples_for 'apache serving a service with mod_wsgi' do
it { should contain_service('httpd').with_name(platform_parameters[:httpd_service_name]) }
it { should contain_class('apache') }
it { should contain_class('apache::mod::wsgi') }
describe 'with default parameters' do
it { should contain_file('/var/www/cgi-bin/keystone').with(
'ensure' => 'directory',
'owner' => 'keystone',
'group' => 'keystone',
'require' => 'Package[httpd]'
)}
it { should contain_file('keystone_wsgi').with(
'ensure' => 'file',
'path' => '/var/www/cgi-bin/keystone/keystone_wsgi',
'source' => '/usr/share/keystone/keystone.wsgi',
'owner' => 'keystone',
'group' => 'keystone',
'mode' => '0644',
)}
it { should 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_process_group' => 'keystone',
'wsgi_script_aliases' => { '/' => "/var/www/cgi-bin/keystone" },
'require' => 'File[keystone_wsgi]'
)}
it { should 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

5
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 { should have_class_count(1) }.to raise_error(Puppet::Error, description)
end
end

@ -1,6 +1,13 @@
require 'puppetlabs_spec_helper/module_spec_helper'
require 'shared_examples'
require 'vcr'
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
VCR.configure do |c|
c.cassette_library_dir = 'spec/fixtures/vcr'
c.hook_into :faraday