Implement Panko Api service

This patch implements api service and other dependent changes.

Change-Id: Iafb31a9d217c211c5099a3b9a420c98731ef1042
This commit is contained in:
Pradeep Kilambi 2016-08-29 13:06:22 -04:00
parent b6830f61b2
commit 85b8ed949a
12 changed files with 667 additions and 15 deletions

View File

@ -14,7 +14,7 @@ panko
Overview
--------
The panko module is a part of [OpenStack](https://www.openstack.org), an effort by the OpenStack infrastructure team to provide continuous integration testing and code review for OpenStack and OpenStack community projects not part of the core software. The module its self is used to flexibly configure and manage the FIXME service for OpenStack.
The panko module is a part of [OpenStack](https://www.openstack.org), an effort by the OpenStack infrastructure team to provide continuous integration testing and code review for OpenStack and OpenStack community projects not part of the core software. The module its self is used to flexibly configure and manage the events service for OpenStack.
Module Description
------------------
@ -26,7 +26,7 @@ Setup
**What the panko module affects**
* [Panko](https://wiki.openstack.org/wiki/Panko), the FIXME service for OpenStack.
* [Panko](https://wiki.openstack.org/wiki/Panko), the events service for OpenStack.
### Installing panko

16
examples/panko.pp Normal file
View File

@ -0,0 +1,16 @@
class { '::panko': }
class { '::panko::keystone::authtoken':
password => 'a_big_secret',
}
class { '::panko::api':
enabled => true,
service_name => 'httpd',
}
include ::apache
class { '::panko::wsgi::apache':
ssl => false,
}
class { '::panko::auth':
auth_password => 'a_big_secret',
}

137
manifests/api.pp Normal file
View File

@ -0,0 +1,137 @@
# Installs & configure the panko api service
#
# == Parameters
#
# [*enabled*]
# (optional) Should the service be enabled.
# Defaults to true
#
# [*manage_service*]
# (optional) Whether the service should be managed by Puppet.
# Defaults to true.
#
# [*host*]
# (optional) The panko api bind address.
# Defaults to 0.0.0.0
#
# [*port*]
# (optional) The panko api port.
# Defaults to 8041
#
# [*workers*]
# (optional) Number of workers for Panko API server.
# Defaults to $::processorcount
#
# [*max_limit*]
# (optional) The maximum number of items returned in a
# single response from a collection resource.
# Defaults to 1000
#
# [*package_ensure*]
# (optional) ensure state for package.
# Defaults to 'present'
#
# [*service_name*]
# (optional) Name of the service that will be providing the
# server functionality of panko-api.
# If the value is 'httpd', this means panko-api will be a web
# service, and you must use another class to configure that
# web service. For example, use class { 'panko::wsgi::apache'...}
# to make panko-api be a web app using apache mod_wsgi.
# Defaults to '$::panko::params::api_service_name'
#
# [*sync_db*]
# (optional) Run panko-upgrade db sync on api nodes after installing the package.
# Defaults to false
#
# [*auth_strategy*]
# (optional) Configure panko authentication.
# Can be set to noauth and keystone.
# Defaults to 'keystone'.
#
class panko::api (
$manage_service = true,
$enabled = true,
$package_ensure = 'present',
$host = '0.0.0.0',
$port = '8779',
$workers = $::processorcount,
$max_limit = 1000,
$service_name = $::panko::params::api_service_name,
$sync_db = false,
$auth_strategy = 'keystone',
) inherits panko::params {
include ::panko::policy
Panko_config<||> ~> Service[$service_name]
Panko_api_paste_ini<||> ~> Service[$service_name]
Class['panko::policy'] ~> Service[$service_name]
Package['panko-api'] -> Service[$service_name]
Package['panko-api'] -> Service['panko-api']
Package['panko-api'] -> Class['panko::policy']
package { 'panko-api':
ensure => $package_ensure,
name => $::panko::params::api_package_name,
tag => ['openstack', 'panko-package'],
}
if $manage_service {
if $enabled {
$service_ensure = 'running'
} else {
$service_ensure = 'stopped'
}
}
if $sync_db {
include ::panko::db::sync
}
if $service_name == $::panko::params::api_service_name {
service { 'panko-api':
ensure => $service_ensure,
name => $::panko::params::api_service_name,
enable => $enabled,
hasstatus => true,
hasrestart => true,
require => Class['panko::db'],
tag => ['panko-service', 'panko-db-sync-service'],
}
} elsif $service_name == 'httpd' {
include ::apache::params
service { 'panko-api':
ensure => 'stopped',
name => $::panko::params::api_service_name,
enable => false,
tag => ['panko-service', 'panko-db-sync-service'],
}
Class['panko::db'] -> Service[$service_name]
Service <<| title == 'httpd' |>> { tag +> 'panko-db-sync-service' }
# we need to make sure panko-api/eventlet is stopped before trying to start apache
Service['panko-api'] -> Service[$service_name]
} else {
fail('Invalid service_name. Either panko/openstack-panko-api for running as a standalone service, or httpd for being run by a httpd server')
}
panko_config {
'api/host': value => $host;
'api/port': value => $port;
'api/workers': value => $workers;
'api/max_limit': value => $max_limit;
}
if $auth_strategy == 'keystone' {
include ::panko::keystone::authtoken
panko_api_paste_ini {
'pipeline:main/pipeline': value => 'panko+auth',
}
} else {
panko_api_paste_ini {
'pipeline:main/pipeline': value => 'panko+noauth',
}
}
}

View File

@ -65,5 +65,5 @@ class panko::db::mysql(
allowed_hosts => $allowed_hosts,
}
::Openstacklib::Db::Mysql['panko'] ~> Exec<| title == 'panko-manage db_sync' |>
::Openstacklib::Db::Mysql['panko'] ~> Exec<| title == 'panko-db-sync' |>
}

View File

@ -50,6 +50,6 @@ class panko::db::postgresql(
privileges => $privileges,
}
::Openstacklib::Db::Postgresql['panko'] ~> Exec<| title == 'panko-manage db_sync' |>
::Openstacklib::Db::Postgresql['panko'] ~> Exec<| title == 'panko-db-sync' |>
}

View File

@ -12,12 +12,15 @@ class panko::db::sync(
$extra_params = undef,
) {
exec { 'panko-db-sync':
command => "panko-manage db_sync ${extra_params}",
command => "panko-dbsync --config-file /etc/panko/panko.conf ${extra_params}",
path => '/usr/bin',
user => 'panko',
refreshonly => true,
subscribe => [Package['panko'], Panko_config['database/connection']],
logoutput => 'on_failure',
}
Exec['panko-manage db_sync'] ~> Service<| title == 'panko' |>
Package<| tag == 'panko-package' |> ~> Exec['panko-db-sync']
Exec['panko-db-sync'] ~> Service<| tag == 'panko-db-sync-service' |>
Panko_config<||> ~> Exec['panko-db-sync']
Panko_config<| title == 'database/connection' |> ~> Exec['panko-db-sync']
}

View File

@ -4,11 +4,31 @@
#
# === Parameters
#
# [*sample_parameter*]
# Explanation of what this parameter affects and what it defaults to.
# [*ensure_package*]
# (optional) The state of panko packages
# Defaults to 'present'
#
class panko {
# [*purge_config*]
# (optional) Whether to set only the specified config options
# in the panko config.
# Defaults to false.
#
class panko (
$ensure_package = 'present',
$purge_config = false,
) inherits panko::params {
include ::panko::params
include ::panko::logging
package { 'panko':
ensure => $ensure_package,
name => $::panko::params::common_package_name,
tag => ['openstack', 'panko-package'],
}
resources { 'panko_config':
purge => $purge_config,
}
}

View File

@ -5,12 +5,18 @@ class panko::params {
case $::osfamily {
'RedHat': {
$api_package_name = 'openstack-panko-api'
$api_service_name = 'openstack-panko-api'
$common_package_name = 'openstack-panko-common'
$api_package_name = 'openstack-panko-api'
$api_service_name = 'openstack-panko-api'
$panko_wsgi_script_path = '/var/www/cgi-bin/panko'
$panko_wsgi_script_source = '/usr/lib/python2.7/site-packages/panko/api/app.wsgi'
}
'Debian': {
$api_package_name = 'panko-api'
$api_service_name = 'panko-api'
$common_package_name = 'panko-common'
$api_package_name = 'panko-api'
$api_service_name = 'panko-api'
$panko_wsgi_script_path = '/usr/lib/cgi-bin/panko'
$panko_wsgi_script_source = '/usr/share/panko-common/app.wsgi'
}
default: {
fail("Unsupported osfamily: ${::osfamily} operatingsystem")

125
manifests/wsgi/apache.pp Normal file
View File

@ -0,0 +1,125 @@
#
#
# 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 to serve panko API with apache mod_wsgi in place of panko-api service.
#
# Serving panko API from apache is the recommended way to go for production
# because of limited performance for concurrent accesses when running eventlet.
#
# When using this class you should disable your panko-api service.
#
# == Parameters
#
# [*servername*]
# The servername for the virtualhost.
# Optional. Defaults to $::fqdn
#
# [*port*]
# The port.
# Optional. Defaults to 8779
#
# [*bind_host*]
# The host/ip address Apache will listen on.
# Optional. Defaults to undef (listen on all ip addresses).
#
# [*path*]
# The prefix for the endpoint.
# Optional. Defaults to '/'
#
# [*ssl*]
# Use ssl ? (boolean)
# Optional. Defaults to true
#
# [*workers*]
# Number of WSGI workers to spawn.
# Optional. Defaults to 1
#
# [*priority*]
# (optional) The priority for the vhost.
# Defaults to '10'
#
# [*threads*]
# (optional) The number of threads for the vhost.
# Defaults to $::processorcount
#
# [*ssl_cert*]
# [*ssl_key*]
# [*ssl_chain*]
# [*ssl_ca*]
# [*ssl_crl_path*]
# [*ssl_crl*]
# [*ssl_certs_dir*]
# apache::vhost ssl parameters.
# Optional. Default to apache::vhost 'ssl_*' defaults.
#
# == Dependencies
#
# requires Class['apache'] & Class['panko']
#
# == Examples
#
# include apache
#
# class { 'panko::wsgi::apache': }
#
class panko::wsgi::apache (
$servername = $::fqdn,
$port = 8779,
$bind_host = undef,
$path = '/',
$ssl = true,
$workers = 1,
$ssl_cert = undef,
$ssl_key = undef,
$ssl_chain = undef,
$ssl_ca = undef,
$ssl_crl_path = undef,
$ssl_crl = undef,
$ssl_certs_dir = undef,
$threads = $::processorcount,
$priority = '10',
) {
include ::panko::params
include ::apache
include ::apache::mod::wsgi
if $ssl {
include ::apache::mod::ssl
}
::openstacklib::wsgi::apache { 'panko_wsgi':
bind_host => $bind_host,
bind_port => $port,
group => 'panko',
path => $path,
priority => $priority,
servername => $servername,
ssl => $ssl,
ssl_ca => $ssl_ca,
ssl_cert => $ssl_cert,
ssl_certs_dir => $ssl_certs_dir,
ssl_chain => $ssl_chain,
ssl_crl => $ssl_crl,
ssl_crl_path => $ssl_crl_path,
ssl_key => $ssl_key,
threads => $threads,
user => 'panko',
workers => $workers,
wsgi_daemon_process => 'panko',
wsgi_process_group => 'panko',
wsgi_script_dir => $::panko::params::panko_wsgi_script_path,
wsgi_script_file => 'app',
wsgi_script_source => $::panko::params::panko_wsgi_script_source,
}
}

View File

@ -0,0 +1,59 @@
require 'spec_helper_acceptance'
describe 'basic panko' do
context 'default parameters' do
it 'should work with no errors' do
pp= <<-EOS
include ::openstack_integration
include ::openstack_integration::repos
include ::openstack_integration::mysql
include ::openstack_integration::keystone
class { '::panko::db::mysql':
password => 'a_big_secret',
}
class { '::panko::keystone::auth':
password => 'a_big_secret',
}
case $::osfamily {
'Debian': {
warning('Panko is not yet packaged on Ubuntu systems.')
}
'RedHat': {
include ::panko
class { '::panko::db':
database_connection => 'mysql+pymysql://panko:a_big_secret@127.0.0.1/panko?charset=utf8',
}
class { '::panko::keystone::authtoken':
password => 'a_big_secret',
}
class { '::panko::api':
enabled => true,
service_name => 'httpd',
}
class { '::panko::db::sync': }
include ::apache
class { '::panko::wsgi::apache':
ssl => false,
}
}
}
EOS
# Run it twice and test for idempotency
apply_manifest(pp, :catch_failures => true)
apply_manifest(pp, :catch_changes => true)
end
if os[:family].casecmp('RedHat') == 0
describe port(8779) do
it { is_expected.to be_listening }
end
end
end
end

View File

@ -0,0 +1,176 @@
require 'spec_helper'
describe 'panko::api' do
let :pre_condition do
"class { 'panko': }
include ::panko::db
class {'panko::keystone::authtoken':
password => 'password',
}"
end
let :params do
{ :enabled => true,
:manage_service => true,
:package_ensure => 'latest',
:port => '8779',
:max_limit => '1000',
:host => '0.0.0.0',
}
end
shared_examples_for 'panko-api' do
it { is_expected.to contain_class('panko::params') }
it { is_expected.to contain_class('panko::policy') }
it 'installs panko-api package' do
is_expected.to contain_package('panko-api').with(
:ensure => 'latest',
:name => platform_params[:api_package_name],
:tag => ['openstack', 'panko-package'],
)
end
it 'configures keystone authentication middleware' do
is_expected.to contain_panko_config('api/host').with_value( params[:host] )
is_expected.to contain_panko_config('api/port').with_value( params[:port] )
is_expected.to contain_panko_config('api/max_limit').with_value( params[:max_limit] )
is_expected.to contain_panko_config('api/workers').with_value('2')
end
[{:enabled => true}, {:enabled => false}].each do |param_hash|
context "when service should be #{param_hash[:enabled] ? 'enabled' : 'disabled'}" do
before do
params.merge!(param_hash)
end
it 'configures panko-api service' do
is_expected.to contain_service('panko-api').with(
:ensure => (params[:manage_service] && params[:enabled]) ? 'running' : 'stopped',
:name => platform_params[:api_service_name],
:enable => params[:enabled],
:hasstatus => true,
:hasrestart => true,
:require => 'Class[Panko::Db]',
:tag => ['panko-service', 'panko-db-sync-service'],
)
end
end
end
context 'with sync_db set to true' do
before do
params.merge!({
:sync_db => true})
end
it { is_expected.to contain_class('panko::db::sync') }
end
context 'with disabled service managing' do
before do
params.merge!({
:manage_service => false,
:enabled => false })
end
it 'configures panko-api service' do
is_expected.to contain_service('panko-api').with(
:ensure => nil,
:name => platform_params[:api_service_name],
:enable => false,
:hasstatus => true,
:hasrestart => true,
:tag => ['panko-service', 'panko-db-sync-service'],
)
end
end
context 'when running panko-api in wsgi' do
before do
params.merge!({ :service_name => 'httpd' })
end
let :pre_condition do
"include ::apache
include ::panko::db
class { 'panko': }
class {'panko::keystone::authtoken':
password => 'password',
}"
end
it 'configures panko-api service with Apache' do
is_expected.to contain_service('panko-api').with(
:ensure => 'stopped',
:name => platform_params[:api_service_name],
:enable => false,
:tag => ['panko-service', 'panko-db-sync-service'],
)
end
end
context 'when service_name is not valid' do
before do
params.merge!({ :service_name => 'foobar' })
end
let :pre_condition do
"include ::apache
include ::panko::db
class { 'panko': }"
end
it_raises 'a Puppet::Error', /Invalid service_name/
end
context "with noauth" do
before do
params.merge!({
:auth_strategy => 'noauth',
})
end
it 'configures pipeline' do
is_expected.to contain_panko_api_paste_ini('pipeline:main/pipeline').with_value('panko+noauth');
end
end
context "with keystone" do
before do
params.merge!({
:auth_strategy => 'keystone',
})
end
it 'configures pipeline' do
is_expected.to contain_panko_api_paste_ini('pipeline:main/pipeline').with_value('panko+auth');
end
end
end
on_supported_os({
:supported_os => OSDefaults.get_supported_os
}).each do |os,facts|
context "on #{os}" do
let (:facts) do
facts.merge!(OSDefaults.get_facts({
:concat_basedir => '/var/lib/puppet/concat',
:processorcount => 2
}))
end
let(:platform_params) do
case facts[:osfamily]
when 'Debian'
{ :api_package_name => 'panko-api',
:api_service_name => 'panko-api' }
when 'RedHat'
{ :api_package_name => 'openstack-panko-api',
:api_service_name => 'openstack-panko-api' }
end
end
it_behaves_like 'panko-api'
end
end
end

View File

@ -0,0 +1,110 @@
require 'spec_helper'
describe 'panko::wsgi::apache' do
shared_examples_for 'apache serving panko with mod_wsgi' do
it { is_expected.to contain_service('httpd').with_name(platform_params[:httpd_service_name]) }
it { is_expected.to contain_class('panko::params') }
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("#{platform_params[:wsgi_script_path]}").with(
'ensure' => 'directory',
'owner' => 'panko',
'group' => 'panko',
'require' => 'Package[httpd]'
)}
it { is_expected.to contain_file('panko_wsgi').with(
'ensure' => 'file',
'path' => "#{platform_params[:wsgi_script_path]}/app",
'source' => platform_params[:wsgi_script_source],
'owner' => 'panko',
'group' => 'panko',
'mode' => '0644'
)}
it { is_expected.to contain_file('panko_wsgi').that_requires("File[#{platform_params[:wsgi_script_path]}]") }
it { is_expected.to contain_apache__vhost('panko_wsgi').with(
'servername' => 'some.host.tld',
'ip' => nil,
'port' => '8779',
'docroot' => "#{platform_params[:wsgi_script_path]}",
'docroot_owner' => 'panko',
'docroot_group' => 'panko',
'ssl' => 'true',
'wsgi_daemon_process' => 'panko',
'wsgi_process_group' => 'panko',
'wsgi_script_aliases' => { '/' => "#{platform_params[:wsgi_script_path]}/app" },
'require' => 'File[panko_wsgi]'
)}
it { is_expected.to contain_concat("#{platform_params[:httpd_ports_file]}") }
end
describe 'when overriding parameters using different ports' do
let :params do
{
:servername => 'dummy.host',
:bind_host => '10.42.51.1',
:port => 12345,
:ssl => false,
:workers => 37,
}
end
it { is_expected.to contain_apache__vhost('panko_wsgi').with(
'servername' => 'dummy.host',
'ip' => '10.42.51.1',
'port' => '12345',
'docroot' => "#{platform_params[:wsgi_script_path]}",
'docroot_owner' => 'panko',
'docroot_group' => 'panko',
'ssl' => 'false',
'wsgi_daemon_process' => 'panko',
'wsgi_process_group' => 'panko',
'wsgi_script_aliases' => { '/' => "#{platform_params[:wsgi_script_path]}/app" },
'require' => 'File[panko_wsgi]'
)}
it { is_expected.to contain_concat("#{platform_params[:httpd_ports_file]}") }
end
end
on_supported_os({
:supported_os => OSDefaults.get_supported_os
}).each do |os,facts|
context "on #{os}" do
let (:facts) do
facts.merge!(OSDefaults.get_facts({
:processorcount => 42,
:concat_basedir => '/var/lib/puppet/concat',
:fqdn => 'some.host.tld',
}))
end
let(:platform_params) do
case facts[:osfamily]
when 'Debian'
{
:httpd_service_name => 'apache2',
:httpd_ports_file => '/etc/apache2/ports.conf',
:wsgi_script_path => '/usr/lib/cgi-bin/panko',
:wsgi_script_source => '/usr/share/panko-common/app.wsgi'
}
when 'RedHat'
{
:httpd_service_name => 'httpd',
:httpd_ports_file => '/etc/httpd/conf/ports.conf',
:wsgi_script_path => '/var/www/cgi-bin/panko',
:wsgi_script_source => '/usr/lib/python2.7/site-packages/panko/api/app.wsgi'
}
end
end
it_behaves_like 'apache serving panko with mod_wsgi'
end
end
end