diff --git a/manifests/api.pp b/manifests/api.pp index 855f45b1..f0ad30c6 100644 --- a/manifests/api.pp +++ b/manifests/api.pp @@ -25,6 +25,15 @@ # (optional) Whether to start/stop the service # Defaults to true # +# [*service_name*] +# (optional) Name of the service that will be providing the +# server functionality of trove-api. +# If the value is 'httpd', this means trove-api will be a web +# service, and you must use another class to configure that +# web service. For example, use class { 'trove::wsgi::apache'...} +# to make trove-api be a web app using apache mod_wsgi. +# Defaults to '$::trove::params::api_service' +# # [*package_ensure*] # (optional) Whether the trove api package will be installed # Defaults to 'present' @@ -95,6 +104,9 @@ # Defaults to $::os_service_default. # class trove::api( + $manage_service = true, + $service_name = $::trove::params::api_service_name, + $package_ensure = 'present', $bind_host = $::os_service_default, $bind_port = $::os_service_default, $backlog = $::os_service_default, @@ -109,16 +121,13 @@ class trove::api( $http_put_rate = $::os_service_default, $http_delete_rate = $::os_service_default, $http_mgmt_post_rate = $::os_service_default, - $manage_service = true, - $package_ensure = 'present', $auth_strategy = 'keystone', $taskmanager_queue = $::os_service_default, -) { +) inherits trove::params { include trove::deps include trove::db include trove::db::sync - include trove::params include trove::api::service_credentials # basic service config @@ -179,11 +188,28 @@ class trove::api( 'DEFAULT/taskmanager_queue': value => $taskmanager_queue; } - trove::generic_service { 'api': - enabled => $enabled, - manage_service => $manage_service, - package_ensure => $package_ensure, - package_name => $::trove::params::api_package_name, - service_name => $::trove::params::api_service_name, + if $service_name == $::trove::params::api_service_name { + trove::generic_service { 'api': + enabled => $enabled, + manage_service => $manage_service, + package_ensure => $package_ensure, + package_name => $::trove::params::api_package_name, + service_name => $service_name, + } + } elsif $service_name == 'httpd' { + trove::generic_service { 'api': + enabled => false, + manage_service => $manage_service, + package_ensure => $package_ensure, + package_name => $::trove::params::api_package_name, + service_name => $::trove::params::api_service_name, + } + if $manage_service { + Service<| title == 'httpd' |> { tag +> 'trove-service' } + Service['trove-api'] -> Service[$service_name] + } + } else { + fail("Invalid service_name. Either trove-api/openstack-trove-api for \ +running as a standalone service, or httpd for being run by a httpd server") } } diff --git a/manifests/params.pp b/manifests/params.pp index 71321651..27439487 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -20,6 +20,8 @@ class trove::params { $guestagent_service_name = 'openstack-trove-guestagent' $taskmanager_package_name = 'openstack-trove-taskmanager' $taskmanager_service_name = 'openstack-trove-taskmanager' + $trove_wsgi_script_dir = '/var/www/cgi-bin/trove' + $trove_wsgi_script_source = '/usr/bin/trove-api' } 'Debian': { $common_package_name = 'trove-common' @@ -31,6 +33,8 @@ class trove::params { $guestagent_service_name = 'trove-guestagent' $taskmanager_package_name = 'trove-taskmanager' $taskmanager_service_name = 'trove-taskmanager' + $trove_wsgi_script_dir = '/usr/lib/cgi-bin/trove' + $trove_wsgi_script_source = '/usr/bin/trove-api' } default: { fail("Unsupported osfamily: ${::osfamily} operatingsystem: ${::operatingsystem}, \ diff --git a/manifests/wsgi/apache.pp b/manifests/wsgi/apache.pp new file mode 100644 index 00000000..bac930cc --- /dev/null +++ b/manifests/wsgi/apache.pp @@ -0,0 +1,209 @@ +# +# Copyright (C) 2023 Red Hat +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# == Class: trove::wsgi::apache +# +# Install Trove API under apache with mod_wsgi. +# +# == Parameters +# +# [*servername*] +# (Optional) The servername for the virtualhost. +# Defaults to $::fqdn +# +# [*port*] +# (Optional) The port. +# Defaults to 8779 +# +# [*bind_host*] +# (Optional) The host/ip address Apache will listen on. +# Defaults to undef (listen on all ip addresses). +# +# [*path*] +# (Optional) The prefix for the endpoint. +# Defaults to '/' +# +# [*ssl*] +# (Optional) Use ssl ? (boolean) +# Defaults to false +# +# [*workers*] +# (Optional) Number of WSGI workers to spawn. +# Defaults to $::os_workers +# +# [*priority*] +# (Optional) The priority for the vhost. +# Defaults to 10 +# +# [*threads*] +# (Optional) The number of threads for the vhost. +# Defaults to 1 +# +# [*wsgi_process_display_name*] +# (Optional) Name of the WSGI process display-name. +# Defaults to undef +# +# [*ssl_cert*] +# [*ssl_key*] +# [*ssl_chain*] +# [*ssl_ca*] +# [*ssl_crl_path*] +# [*ssl_crl*] +# [*ssl_certs_dir*] +# (Optional) apache::vhost ssl parameters. +# Default to apache::vhost 'ssl_*' defaults. +# +# [*access_log_file*] +# (Optional) The log file name for the virtualhost. +# Defaults to undef. +# +# [*access_log_pipe*] +# (Optional) Specifies a pipe where Apache sends access logs for +# the virtualhost. +# Defaults to undef. +# +# [*access_log_syslog*] +# (Optional) Sends the virtualhost access log messages to syslog. +# Defaults to undef. +# +# [*access_log_format*] +# (Optional) The log format for the virtualhost. +# Defaults to undef. +# +# [*error_log_file*] +# (Optional) The error log file name for the virtualhost. +# Defaults to undef. +# +# [*error_log_pipe*] +# (Optional) Specifies a pipe where Apache sends error logs for +# the virtualhost. +# Defaults to undef. +# +# [*error_log_syslog*] +# (Optional) Sends the virtualhost error log messages to syslog. +# Defaults to undef. +# +# [*custom_wsgi_process_options*] +# (Optional) gives you the opportunity to add custom process options or to +# overwrite the default options for the WSGI main process. +# eg. to use a virtual python environment for the WSGI process +# you could set it to: +# { python-path => '/my/python/virtualenv' } +# Defaults to {} +# +# [*wsgi_script_dir*] +# (Optional) The directory to install the WSGI script for apache to read. +# Defaults to $::trove::params::trove_wsgi_script_path +# +# [*wsgi_script_source*] +# (Optional) The location of the trove WSGI script +# Defaults to $::trove::params::trove_wsgi_script_source +# +# [*headers*] +# (Optional) Headers for the vhost. +# Defaults to undef +# +# [*request_headers*] +# (Optional) Modifies collected request headers in various ways. +# Defaults to undef +# +# [*vhost_custom_fragment*] +# (Optional) Passes a string of custom configuration +# directives to be placed at the end of the vhost configuration. +# Defaults to undef. +# +# == Dependencies +# +# requires Class['apache'] & Class['trove'] +# +# == Examples +# +# include apache +# +# class { 'trove::wsgi::apache': } +# +class trove::wsgi::apache ( + $servername = $::fqdn, + $port = 8779, + $bind_host = undef, + $path = '/', + $ssl = false, + $workers = $::os_workers, + $ssl_cert = undef, + $ssl_key = undef, + $ssl_chain = undef, + $ssl_ca = undef, + $ssl_crl_path = undef, + $ssl_crl = undef, + $ssl_certs_dir = undef, + $wsgi_process_display_name = undef, + $threads = 1, + $priority = 10, + $access_log_file = undef, + $access_log_pipe = undef, + $access_log_syslog = undef, + $access_log_format = undef, + $error_log_file = undef, + $error_log_pipe = undef, + $error_log_syslog = undef, + $custom_wsgi_process_options = {}, + $wsgi_script_dir = $::trove::params::trove_wsgi_script_dir, + $wsgi_script_source = $::trove::params::trove_wsgi_script_source, + $headers = undef, + $request_headers = undef, + $vhost_custom_fragment = undef, +) inherits trove::params { + + include trove::deps + + Anchor['trove::install::end'] -> Class['apache'] + + openstacklib::wsgi::apache { 'trove_wsgi': + bind_host => $bind_host, + bind_port => $port, + group => $::trove::params::group, + 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 => $::trove::params::user, + vhost_custom_fragment => $vhost_custom_fragment, + workers => $workers, + wsgi_daemon_process => 'trove', + wsgi_process_display_name => $wsgi_process_display_name, + wsgi_process_group => 'trove', + wsgi_script_dir => $wsgi_script_dir, + wsgi_script_file => 'app', + wsgi_script_source => $wsgi_script_source, + headers => $headers, + request_headers => $request_headers, + custom_wsgi_process_options => $custom_wsgi_process_options, + access_log_file => $access_log_file, + access_log_pipe => $access_log_pipe, + access_log_syslog => $access_log_syslog, + access_log_format => $access_log_format, + error_log_file => $error_log_file, + error_log_pipe => $error_log_pipe, + error_log_syslog => $error_log_syslog, + } +} diff --git a/releasenotes/notes/wsgi-c8adcf992c49ea50.yaml b/releasenotes/notes/wsgi-c8adcf992c49ea50.yaml new file mode 100644 index 00000000..7770ef3b --- /dev/null +++ b/releasenotes/notes/wsgi-c8adcf992c49ea50.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Now this module supports deploying trove-api using httpd and mod_wsgi. + Use the ``trove::wsgi::apache`` class to set up vhost for trove API. Note + the ``trove::api::service_name`` parameter should be set to ``httpd`` in + case httpd is used. diff --git a/spec/classes/trove_wsgi_apache_spec.rb b/spec/classes/trove_wsgi_apache_spec.rb new file mode 100644 index 00000000..28e1c7b7 --- /dev/null +++ b/spec/classes/trove_wsgi_apache_spec.rb @@ -0,0 +1,177 @@ +require 'spec_helper' + +describe 'trove::wsgi::apache' do + + shared_examples_for 'apache serving trove with mod_wsgi' do + context 'with default parameters' do + it { is_expected.to contain_class('trove::params') } + it { is_expected.to contain_openstacklib__wsgi__apache('trove_wsgi').with( + :bind_port => 8779, + :group => 'trove', + :path => '/', + :priority => 10, + :servername => facts[:fqdn], + :ssl => false, + :threads => 1, + :user => 'trove', + :workers => facts[:os_workers], + :wsgi_daemon_process => 'trove', + :wsgi_process_group => 'trove', + :wsgi_script_dir => platform_params[:wsgi_script_path], + :wsgi_script_file => 'app', + :wsgi_script_source => platform_params[:wsgi_script_source], + :headers => nil, + :request_headers => nil, + :custom_wsgi_process_options => {}, + :access_log_file => nil, + :access_log_pipe => nil, + :access_log_syslog => nil, + :access_log_format => nil, + :error_log_file => nil, + :error_log_pipe => nil, + :error_log_syslog => nil, + )} + end + + context 'when overriding parameters' do + let :params do + { + :servername => 'dummy.host', + :bind_host => '10.42.51.1', + :port => 12345, + :ssl => true, + :wsgi_process_display_name => 'trove', + :workers => 37, + :custom_wsgi_process_options => { + 'python_path' => '/my/python/path', + }, + :wsgi_script_dir => '/var/lib/openstack/cgi-bin/trove', + :wsgi_script_source => '/my/path/app.wsgi', + :headers => ['set X-XSS-Protection "1; mode=block"'], + :request_headers => ['set Content-Type "application/json"'], + :vhost_custom_fragment => 'Timeout 99' + } + end + it { is_expected.to contain_class('trove::params') } + it { is_expected.to contain_openstacklib__wsgi__apache('trove_wsgi').with( + :bind_host => '10.42.51.1', + :bind_port => 12345, + :group => 'trove', + :path => '/', + :servername => 'dummy.host', + :ssl => true, + :threads => 1, + :user => 'trove', + :workers => 37, + :vhost_custom_fragment => 'Timeout 99', + :wsgi_daemon_process => 'trove', + :wsgi_process_display_name => 'trove', + :wsgi_process_group => 'trove', + :wsgi_script_dir => '/var/lib/openstack/cgi-bin/trove', + :wsgi_script_file => 'app', + :wsgi_script_source => '/my/path/app.wsgi', + :headers => ['set X-XSS-Protection "1; mode=block"'], + :request_headers => ['set Content-Type "application/json"'], + :custom_wsgi_process_options => { + 'python_path' => '/my/python/path', + }, + )} + end + + context 'with custom access logging' do + let :params do + { + :access_log_format => 'foo', + :access_log_syslog => 'syslog:local0', + :error_log_syslog => 'syslog:local1', + } + end + + it { should contain_openstacklib__wsgi__apache('trove_wsgi').with( + :access_log_format => params[:access_log_format], + :access_log_syslog => params[:access_log_syslog], + :error_log_syslog => params[:error_log_syslog], + )} + end + + context 'with access_log_file' do + let :params do + { + :access_log_file => '/path/to/file', + } + end + + it { should contain_openstacklib__wsgi__apache('trove_wsgi').with( + :access_log_file => params[:access_log_file], + )} + end + + context 'with access_log_pipe' do + let :params do + { + :access_log_pipe => 'pipe', + } + end + + it { should contain_openstacklib__wsgi__apache('trove_wsgi').with( + :access_log_pipe => params[:access_log_pipe], + )} + end + + context 'with error_log_file' do + let :params do + { + :error_log_file => '/path/to/file', + } + end + + it { should contain_openstacklib__wsgi__apache('trove_wsgi').with( + :error_log_file => params[:error_log_file], + )} + end + + context 'with error_log_pipe' do + let :params do + { + :error_log_pipe => 'pipe', + } + end + + it { should contain_openstacklib__wsgi__apache('trove_wsgi').with( + :error_log_pipe => params[:error_log_pipe], + )} + 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({ + :os_workers => 8, + :concat_basedir => '/var/lib/puppet/concat', + :fqdn => 'some.host.tld' + })) + end + + let(:platform_params) do + case facts[:osfamily] + when 'Debian' + { + :wsgi_script_path => '/usr/lib/cgi-bin/trove', + :wsgi_script_source => '/usr/bin/trove-api' + } + when 'RedHat' + { + :wsgi_script_path => '/var/www/cgi-bin/trove', + :wsgi_script_source => '/usr/bin/trove-api' + } + + end + end + it_configures 'apache serving trove with mod_wsgi' + end + end + +end