Allow for both global zuul web and whitelabeled tenant

This updates the zuul web config to manage both global web server and
whitelabeled per tenant webserver configs. A new set of config hashes is
introduced to do this. For backward compatibility we construct the
hashes from existing parameters if the new hashes are unset.

Change-Id: Ie8ba46111530e74b8b1d0ec1746df2e09754fe67
This commit is contained in:
Clark Boylan 2019-01-28 11:16:35 -08:00
parent 8d7b9c8ab4
commit f85574113e
4 changed files with 176 additions and 108 deletions

49
manifests/ssl_files.pp Normal file
View File

@ -0,0 +1,49 @@
# 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.
# == Define: zuul::ssl_files
#
define zuul::ssl_files (
$ssl_cert_file_contents,
$ssl_key_file_contents,
$ssl_chain_file_contents,
) {
file { "/etc/ssl/certs/${name}.pem":
ensure => present,
owner => 'root',
group => 'root',
mode => '0644',
content => $ssl_cert_file_contents,
require => File['/etc/ssl/certs'],
before => Httpd::Vhost[$name],
}
file { "/etc/ssl/private/${name}.key":
ensure => present,
owner => 'root',
group => 'root',
mode => '0600',
content => $ssl_key_file_contents,
require => File['/etc/ssl/private'],
before => Httpd::Vhost[$name],
}
if $ssl_chain_file_contents != '' {
file { "/etc/ssl/certs/${name}_intermediate.pem":
ensure => present,
owner => 'root',
group => 'root',
mode => '0644',
content => $ssl_chain_file_contents,
require => File['/etc/ssl/certs'],
before => Httpd::Vhost[$name],
}
}
}

View File

@ -0,0 +1,52 @@
# 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.
# == Define: zuul::status_backups
#
define zuul::status_backups (
$tenant_name,
$ssl,
) {
if tenant_name and tenant_name != '' {
if $ssl {
$status = "https://${name}/api/status"
} else {
$status = "http://${name}/api/status"
}
# Minutes, hours, days, etc are not specified here because we are
# interested in running this *every minute*.
# This is a mean of backing up status.json periodically in order to provide
# a mean of restoring lost scheduler queues if need be.
# We are downloading this file at a location served by the vhost so that we
# can query it easily should the need arise.
# If the status.json is unavailable for download, no new files are created.
cron { "zuul_scheduler_status_backup-${name}":
user => 'root',
command => "timeout -k 5 10 curl ${status} -o /var/lib/zuul/backup/${name}_status_$(date +\\%s).json 2>/dev/null",
require => [Package['curl'],
User['zuul'],
File['/var/lib/zuul/backup']],
}
# Rotate backups and keep no more than 120 files -- or 2 hours worth of
# backup if Zuul has 100% uptime.
# We're not basing the rotation on time because the scheduler/web service
# could be down for an extended period of time.
# This is ran hourly so technically up to ~3 hours worth of backups will
# be kept.
cron { "zuul_scheduler_status_prune-${name}":
user => 'root',
minute => '0',
command => "flock -n /var/run/${name}_status_prune.lock ls -dt -1 /var/lib/zuul/backup/${name}_* |sed -e '1,120d' |xargs rm -f",
require => Cron["zuul_scheduler_status_backup-${name}"],
}
}
}

View File

@ -27,8 +27,62 @@ class zuul::web (
$ssl_chain_file_contents = '',
$block_referers = [],
$serveradmin = "webmaster@${::fqdn}",
# New sets of hashes on which create resources will be run.
# If not supplied the legacy parameters above will be used to
# construct these hashes.
$vhosts = {},
$vhosts_flags = {},
$vhosts_ssl = {},
) {
$web_url = "http://${web_listen_address}:${web_listen_port}"
$websocket_url = "ws://${web_listen_address}:${web_listen_port}"
$zuul_web_root = '/opt/zuul-web'
$zuul_web_content_root = '/opt/zuul-web/content'
$zuul_web_src_root = '/opt/zuul-web/source'
$zuul_web_filename = 'zuul-content-latest.tar.gz'
$zuul_web_url = "http://tarballs.openstack.org/zuul/${zuul_web_filename}"
if $vhosts == {} {
if $ssl_cert_file_contents == '' {
$vhost_port = 80
$use_ssl = false
$vhosts_ssl_int = {}
}
else {
$vhost_port = 443
$use_ssl = true
$vhosts_ssl_int = {
"${vhost_name}" => {
ssl_cert_file_contents => $ssl_cert_file_contents,
ssl_key_file_contents => $ssl_key_file_contents,
ssl_chain_file_contents => $ssl_chain_file_contents,
}
}
}
$vhosts_int = {
"${vhost_name}" => {
port => $vhost_port,
docroot => $zuul_web_content_root,
priority => '50',
ssl => $use_ssl,
template => 'zuul/zuulv3.vhost.erb',
vhost_name => $vhost_name,
}
}
$vhosts_flags_int = {
"${vhost_name}" => {
tenant_name => $tenant_name,
ssl => $use_ssl,
}
}
}
else {
$vhosts_ssl_int = $vhosts_ssl
$vhosts_int = $vhosts
$vhosts_flags_int = $vhosts_flags
}
service { 'zuul-web':
ensure => $ensure,
name => 'zuul-web',
@ -97,94 +151,9 @@ class zuul::web (
}
if $enable_status_backups {
# Minutes, hours, days, etc are not specified here because we are
# interested in running this *every minute*.
# This is a mean of backing up status.json periodically in order to provide
# a mean of restoring lost scheduler queues if need be.
# We are downloading this file at a location served by the vhost so that we
# can query it easily should the need arise.
# If the status.json is unavailable for download, no new files are created.
if $ssl_cert_file_contents != '' {
$status = "https://${vhost_name}/api/status"
} else {
$status = "http://${vhost_name}/api/status"
}
cron { 'zuul_scheduler_status_backup':
user => 'root',
command => "timeout -k 5 10 curl ${status} -o /var/lib/zuul/backup/status_$(date +\\%s).json 2>/dev/null",
require => [Package['curl'],
User['zuul'],
File['/var/lib/zuul/backup']],
}
# Rotate backups and keep no more than 120 files -- or 2 hours worth of
# backup if Zuul has 100% uptime.
# We're not basing the rotation on time because the scheduler/web service
# could be down for an extended period of time.
# This is ran hourly so technically up to ~3 hours worth of backups will
# be kept.
cron { 'zuul_scheduler_status_prune':
user => 'root',
minute => '0',
command => 'flock -n /var/run/status_prune.lock ls -dt -1 /var/lib/zuul/backup/* |sed -e "1,120d" |xargs rm -f',
require => Cron['zuul_scheduler_status_backup'],
}
create_resources(zuul::status_backups, $vhosts_flags_int)
}
if $ssl_cert_file_contents == '' {
$use_ssl = false
} else {
$use_ssl = true
file { '/etc/ssl/certs':
ensure => directory,
owner => 'root',
group => 'root',
mode => '0755',
}
file { '/etc/ssl/private':
ensure => directory,
owner => 'root',
group => 'root',
mode => '0700',
}
file { "/etc/ssl/certs/${vhost_name}.pem":
ensure => present,
owner => 'root',
group => 'root',
mode => '0644',
content => $ssl_cert_file_contents,
require => File['/etc/ssl/certs'],
before => Httpd::Vhost[$vhost_name],
}
file { "/etc/ssl/private/${vhost_name}.key":
ensure => present,
owner => 'root',
group => 'root',
mode => '0600',
content => $ssl_key_file_contents,
require => File['/etc/ssl/private'],
before => Httpd::Vhost[$vhost_name],
}
if $ssl_chain_file_contents != '' {
file { "/etc/ssl/certs/${vhost_name}_intermediate.pem":
ensure => present,
owner => 'root',
group => 'root',
mode => '0644',
content => $ssl_chain_file_contents,
require => File['/etc/ssl/certs'],
before => Httpd::Vhost[$vhost_name],
}
}
}
$web_url = "http://${web_listen_address}:${web_listen_port}"
$websocket_url = "ws://${web_listen_address}:${web_listen_port}"
$zuul_web_root = '/opt/zuul-web'
$zuul_web_content_root = '/opt/zuul-web/content'
$zuul_web_src_root = '/opt/zuul-web/source'
$zuul_web_filename = 'zuul-content-latest.tar.gz'
$zuul_web_url = "http://tarballs.openstack.org/zuul/${zuul_web_filename}"
file { $zuul_web_root:
ensure => directory,
group => 'zuul',
@ -251,24 +220,6 @@ class zuul::web (
subscribe => Exec['unpack-zuul-web'],
}
::httpd::vhost { $vhost_name:
port => 80,
docroot => $zuul_web_content_root,
priority => '50',
ssl => false,
template => 'zuul/zuulv3.vhost.erb',
vhost_name => $vhost_name,
}
if $use_ssl {
::httpd::vhost { "${vhost_name}-ssl":
port => 443,
docroot => $zuul_web_content_root,
priority => '50',
ssl => true,
template => 'zuul/zuulv3.vhost.erb',
vhost_name => $vhost_name,
}
}
if ! defined(Httpd::Mod['rewrite']) {
httpd::mod { 'rewrite': ensure => present }
}
@ -288,4 +239,20 @@ class zuul::web (
httpd::mod { 'cache_disk': ensure => present }
}
if $vhosts_ssl_int != {} {
file { '/etc/ssl/certs':
ensure => directory,
owner => 'root',
group => 'root',
mode => '0755',
}
file { '/etc/ssl/private':
ensure => directory,
owner => 'root',
group => 'root',
mode => '0700',
}
create_resources(zuul::ssl_files, $vhosts_ssl_int)
}
create_resources(httpd::vhost, $vhosts_int)
}

View File

@ -8,7 +8,7 @@
SSLProtocol All -SSLv2 -SSLv3
SSLCertificateFile /etc/ssl/certs/<%= @vhost_name %>.pem
SSLCertificateKeyFile /etc/ssl/private/<%= @vhost_name %>.key
<% if scope.lookupvar('::zuul::web::ssl_chain_file_contents') != '' -%>
<% if scope.lookupvar('::zuul::web::vhosts_ssl_int')[@vhost_name]['ssl_chain_file_contents'] != '' -%>
SSLCertificateChainFile /etc/ssl/certs/<%= @vhost_name %>_intermediate.pem
<% end -%>
<% end -%>
@ -40,10 +40,10 @@
RewriteRule ^/status - [F]
<% end -%>
<% if scope.lookupvar('::zuul::web::tenant_name') != '' -%>
<% if scope.lookupvar('::zuul::web::vhosts_flags_int')[@vhost_name]['tenant_name'] != '' -%>
RewriteRule ^/api/connection/(.*)$ <%= scope.lookupvar('::zuul::web::web_url') %>/api/connection/$1 [P,L]
RewriteRule ^/api/console-stream <%= scope.lookupvar('::zuul::web::websocket_url') %>/api/tenant/<%= scope.lookupvar('::zuul::web::tenant_name') %>/console-stream [P,L]
RewriteRule ^/api/(.*)$ <%= scope.lookupvar('::zuul::web::web_url') %>/api/tenant/<%= scope.lookupvar('::zuul::web::tenant_name') %>/$1 [P,L]
RewriteRule ^/api/console-stream <%= scope.lookupvar('::zuul::web::websocket_url') %>/api/tenant/<%= scope.lookupvar('::zuul::web::vhosts_flags_int')[@vhost_name]['tenant_name'] %>/console-stream [P,L]
RewriteRule ^/api/(.*)$ <%= scope.lookupvar('::zuul::web::web_url') %>/api/tenant/<%= scope.lookupvar('::zuul::web::vhosts_flags_int')[@vhost_name]['tenant_name'] %>/$1 [P,L]
<% else -%>
RewriteRule ^/t/(.*) /$1 [L]
RewriteRule ^/api/tenant/(.*)/console-stream <%= scope.lookupvar('::zuul::web::websocket_url') %>/api/tenant/$1/console-stream [P,L]