diff --git a/install_modules.sh b/install_modules.sh index 44c63a79dd..3948617721 100755 --- a/install_modules.sh +++ b/install_modules.sh @@ -54,6 +54,7 @@ MODULES["puppetlabs-inifile"]="1.0.0" MODULES["puppetlabs-firewall"]="0.0.4" MODULES["puppetlabs-puppetdb"]="3.0.1" MODULES["stankevich-python"]="1.6.6" +MODULES["example42-puppi"]="2.1.9" SOURCE_MODULES["https://github.com/nibalizer/puppet-module-puppetboard"]="2.4.0" diff --git a/manifests/site.pp b/manifests/site.pp index d0411ee8d2..fe3fb915a1 100644 --- a/manifests/site.pp +++ b/manifests/site.pp @@ -422,7 +422,7 @@ node 'storyboard.openstack.org' { mysql_password => hiera('storyboard_db_password', 'XXX'), ssl_cert_file_contents => hiera('storyboard_ssl_cert_file_contents', 'XXX'), ssl_key_file_contents => hiera('storyboard_ssl_key_file_contents', 'XXX'), - ssl_chain_file_contents => hiera('storyboard_ssl_chain_file_contents', 'XXX'), + ssl_chain_file_contents => hiera('storyboard_ssl_chain_file_contents', 'XXX') } } diff --git a/modules/openstack_project/manifests/storyboard.pp b/modules/openstack_project/manifests/storyboard.pp index bcd6cf9190..6369a15556 100644 --- a/modules/openstack_project/manifests/storyboard.pp +++ b/modules/openstack_project/manifests/storyboard.pp @@ -5,31 +5,40 @@ class openstack_project::storyboard( $mysql_password = '', $mysql_user = '', $sysadmins = [], - $ssl_cert_file_contents = '', - $ssl_key_file_contents = '', - $ssl_chain_file_contents = '', + $ssl_cert_file_contents = undef, + $ssl_key_file_contents = undef, + $ssl_chain_file_contents = undef, + $openid_url = 'https://login.launchpad.net/+openid' ) { class { 'openstack_project::server': sysadmins => $sysadmins, iptables_public_tcp_ports => [80, 443], } - class { '::storyboard': - mysql_host => $mysql_host, - mysql_password => $mysql_password, - mysql_user => $mysql_user, - projects_file => - 'puppet:///modules/openstack_project/review.projects.yaml', - superusers_file => - 'puppet:///modules/openstack_project/storyboard/superusers.yaml', - ssl_cert_file => - '/etc/ssl/certs/storyboard.openstack.org.pem', - ssl_key_file => - '/etc/ssl/private/storyboard.openstack.org.key', - ssl_chain_file => '/etc/ssl/certs/intermediate.pem', - ssl_cert_file_contents => $ssl_cert_file_contents, - ssl_key_file_contents => $ssl_key_file_contents, - ssl_chain_file_contents => $ssl_chain_file_contents, + class { '::storyboard::cert': + ssl_cert_content => $ssl_cert_file_contents, + ssl_cert => '/etc/ssl/certs/storyboard.openstack.org.pem', + ssl_key_content => $ssl_key_file_contents, + ssl_key => '/etc/ssl/private/storyboard.openstack.org.key', + ssl_ca_content => $ssl_chain_file_contents } + class { '::storyboard::application': + hostname => $::fqdn, + openid_url => $openid_url, + mysql_host => $mysql_host, + mysql_database => 'storyboard', + mysql_user => $mysql_user, + mysql_user_password => $mysql_password + } + + # Load the projects into the database. + class { '::storyboard::load_projects': + source => 'puppet:///modules/openstack_project/review.projects.yaml', + } + + # Load the superusers into the database + class { '::storyboard::load_superusers': + source => 'puppet:///modules/openstack_project/storyboard/superusers.yaml', + } } diff --git a/modules/storyboard/Modulefile b/modules/storyboard/Modulefile new file mode 100644 index 0000000000..e8ce4695b3 --- /dev/null +++ b/modules/storyboard/Modulefile @@ -0,0 +1,15 @@ +name 'openstack-storyboard' +version '0.0.1' +source 'git://git.openstack.org/openstack-infra/puppet-storyboard.git' +author 'openstackci' +license 'Apache 2.0' +summary 'Puppet module for the OpenStack StoryBoard' +description 'This module configures StoryBoard either as a standalone, localhost instance or as a fully configurable WSGI app.' +project_page 'https://github.com/openstack-ci/puppet-storyboard' + +## Add dependencies, if any: +dependency 'puppetlabs/mysql', '= 0.6.1' +dependency 'puppetlabs/apache', '= 0.0.4' +dependency 'example42/puppi', '= 2.1.9' +dependency 'openstackci/vcsrepo', '= 0.0.8' +dependency 'stankevich/python', '= 1.6.6' \ No newline at end of file diff --git a/modules/storyboard/README.md b/modules/storyboard/README.md new file mode 100644 index 0000000000..670ede3518 --- /dev/null +++ b/modules/storyboard/README.md @@ -0,0 +1,168 @@ +# OpenStack StoryBoard Module + +Michael Krotscheck + +This module manages and installs OpenStack StoryBoard. It can be installed +either as a standalone instance with all dependencies included, or +buffet-style per component. + +# Quick Start + +To install StoryBoard and configure it with sane defaults, include the +following in your site.pp file: + + node default { + include storyboard + } + +# Configuration + +The StoryBoard puppet module is separated into individual components which +StoryBoard needs to run. These can either be installed independently with +their own configurations, or with the centralized configuration provided by +the storyboard module. For specific configuration options, please see the +appropriate section. + +## ::storyboard +A module that installs a standalone instance of StoryBoard. + +The standalone StoryBoard module will install a fully functional, independent +instance of StoryBoard on your node. It includes a local instance of mysql, +an HTTPS vhost using the apache snakeoil certificates, and an automatic +redirect from http://$hostname to https://$hostname/. + + node default { + class { 'storyboard': + mysql_database => 'storyboard', + mysql_user => 'storyboard', + mysql_user_password => 'changeme', + hostname => ::fqdn, + openid_url => 'https://login.launchpad.net/+openid', + ssl_cert_file => '/etc/ssl/certs/ssl-cert-snakeoil.pem', + ssl_cert_content => undef, + ssl_key_file => '/etc/ssl/private/ssl-cert-snakeoil.key', + ssl_key_content => undef, + ssl_ca_file => undef, + ssl_ca_content => undef + } + } + +NOTE: If you don't want an SSL host, set all of the ssl_* parameters to +undef. + +## ::storyboard::mysql +A module that installs a local mysql database for StoryBoard + +This module installs a standalone mysql instance with a StoryBoard database +and a user that is able to access. It is used by the +::storyboard to provide the database, and may be used for minor +customizations of a standalone-like install. + + node default { + class { 'storyboard::mysql': + mysql_database => 'storyboard', + mysql_user => 'storyboard', + mysql_user_password => 'changeme' + } + } + +## ::storyboard::cert +A module that installs an ssl certificate chain for StoryBoard + +This module can be used if you want to add SSL/TLS support to the apache +instance that is hosting StoryBoard. Simply tell it where it should read +the contents of the various certificates and keys from, and it will move +them into the correct place for StoryBoard. + +Note that this module supports both string content certificates or file +references. To pick one over the other, make sure that the undesired method +is set to undef. You can also customize where the certificate +will be saved, however that's not strictly necessary. + + node default { + class { 'storyboard::cert': + $ssl_cert_file = undef, + $ssl_cert_content = undef, + $ssl_cert = '/etc/ssl/certs/storyboard.openstack.org.pem', + + $ssl_key_file = undef, + $ssl_key_content = undef, + $ssl_key = '/etc/ssl/private/storyboard.openstack.org.key', + + $ssl_ca_file = undef, + $ssl_ca_content = undef, + $ssl_ca = '/etc/ssl/certs/ca.pem' + } + } + +## ::storyboard::application +A module that installs the storyboard webclient and API. + +This module can be used if you want to provide your own database, and only +want the API, webclient, and storyboard configuration managed on your node. +It will automatically detect the existence of storyboard::cert, +and adjust the apache vhost accordingly. + + node default { + class { 'storyboard::application': + # Installation parameters + www_root => '/var/lib/storyboard/www', + server_admin => undef, + hostname => ::fqdn, + + # storyboard.conf parameters + access_token_ttl => 3600, + refresh_token_ttl => 604800, + openid_url => 'https://login.launchpad.net/+openid', + mysql_host => 'localhost', + mysql_port => 3306, + mysql_database => 'storyboard', + mysql_user => 'storyboard', + mysql_user_password => 'changeme' + } + } + +## ::storyboard::load_projects +A module that seeds the database with a predefined list of projects. + +This module will maintain the list of projects in the storyboard database, +and keep it up to date with the content of the provided configuration file. +Projects not found in the file will be deleted, projects not found in the +database will be added. Note that the 'use-storyboard' flag MUST be set. + + node default { + class { 'storyboard::load_projects': + source => 'puppet:///modules/openstack_project/projects.yaml' + } + } + +File content format: + + - project: openstack/storyboard + description: The StoryBoard API + use-storyboard: true + - project: openstack/storyboard-webclient + description: The StoryBoard HTTP client + use-storyboard: true + +## ::storyboard::load_superusers +A module that maintains the list of superusers. + +This module will maintain the list of superusers (administrators) in the +storyboard database, and keep it up to date with the content of the provided +configuration file. Users are referenced by openID and keyed by email +address, however all other information will be persisted from the +OpenID provider. + + node default { + class { 'storyboard::load_superusers': + source => 'puppet:///modules/openstack_project/superusers.yaml' + } + } + +File content format: + + - openid: https://login.launchpad.net/+id/some_openid + email: your_email@some_email_host.com + - openid: https://login.launchpad.net/+id/some_other_id + email: admin_email@some_email_host.com \ No newline at end of file diff --git a/modules/storyboard/manifests/application.pp b/modules/storyboard/manifests/application.pp new file mode 100644 index 0000000000..ae8efc3738 --- /dev/null +++ b/modules/storyboard/manifests/application.pp @@ -0,0 +1,172 @@ +# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. +# +# 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: storyboard::application +# +# This module installs the storyboard webclient and the api onto the current +# host. If storyboard::cert is defined, it will use a https vhost, otherwise +# it'll just use http. +# +class storyboard::application ( + + # Installation parameters + $www_root = '/var/lib/storyboard/www', + $server_admin = undef, + $hostname = $::fqdn, + + # storyboard.conf parameters + $access_token_ttl = 3600, + $refresh_token_ttl = 604800, + $openid_url, + $mysql_host = 'localhost', + $mysql_port = 3306, + $mysql_database = 'storyboard', + $mysql_user = 'storyboard', + $mysql_user_password = 'changeme', +) { + + # Dependencies + require storyboard::params + include apache + include apache::mod::wsgi + + class { 'python': + pip => true, + dev => true, + } + include python::install + include mysql::python + + if !defined(Package['git']) { + package { 'git': + ensure => present + } + } + + # Configure the StoryBoard API + file { '/etc/storyboard.conf': + ensure => present, + owner => $storyboard::params::user, + group => $storyboard::params::group, + mode => '0400', + content => template('storyboard/storyboard.conf.erb'), + notify => Service['httpd'], + require => Class['apache::params'], + } + + # Download the latest StoryBoard Source + vcsrepo { '/opt/storyboard': + ensure => latest, + provider => git, + revision => 'master', + source => 'https://git.openstack.org/openstack-infra/storyboard/', + require => Package['git'] + } + + # Run pip + exec { 'install-storyboard' : + command => 'pip install /opt/storyboard', + path => '/usr/local/bin:/usr/bin:/bin/', + refreshonly => true, + subscribe => Vcsrepo['/opt/storyboard'], + notify => Service['httpd'], + require => [ + Class['apache::params'], + Class['python::install'], + ] + } + + # Create the root dir + file { '/var/lib/storyboard': + ensure => directory, + owner => $storyboard::params::user, + group => $storyboard::params::group, + } + + # Create the log dir + file { '/var/log/storyboard': + ensure => directory, + owner => $storyboard::params::user, + group => $storyboard::params::group, + } + + # Install the wsgi app + file { '/var/lib/storyboard/storyboard.wsgi': + source => '/opt/storyboard/storyboard/api/app.wsgi', + owner => $storyboard::params::user, + group => $storyboard::params::group, + require => [ + File['/var/lib/storyboard'], + Exec['install-storyboard'], + ], + notify => Service['httpd'], + } + + # Migrate the database + exec { 'migrate-storyboard-db': + command => 'storyboard-db-manage --config-file /etc/storyboard.conf upgrade head', + path => '/usr/local/bin:/usr/bin:/bin/', + refreshonly => true, + subscribe => [ + Exec['install-storyboard'], + File['/etc/storyboard.conf'], + ], + require => [ + Class['mysql::python'], + File['/etc/storyboard.conf'], + ], + notify => Service['httpd'], + } + + # Download the latest storyboard-webclient + puppi::netinstall { 'storyboard-webclient': + url => 'http://tarballs.openstack.org/storyboard-webclient/storyboard-webclient-latest.tar.gz', + destination_dir => '/opt/storyboard-webclient', + extracted_dir => 'dist', + } + + # Copy the downloaded source into the configured www_root + file { $www_root: + ensure => directory, + owner => $storyboard::params::user, + group => $storyboard::params::group, + require => Puppi::Netinstall['storyboard-webclient'], + source => '/opt/storyboard-webclient/dist', + recurse => true, + purge => true, + force => true, + notify => Service['httpd'], + } + + # Are we setting up TLS or non-TLS? + if defined(Class['storyboard::cert']) { + # Set up storyboard as HTTPS + apache::vhost { $hostname: + port => 443, + docroot => $www_root, + priority => '50', + template => 'storyboard/storyboard_https.vhost.erb', + ssl => true, + } + } else { + # Set up storyboard as HTTPS + apache::vhost { $hostname: + port => 80, + docroot => $www_root, + priority => '50', + template => 'storyboard/storyboard_http.vhost.erb', + ssl => false, + } + } +} \ No newline at end of file diff --git a/modules/storyboard/manifests/cert.pp b/modules/storyboard/manifests/cert.pp new file mode 100644 index 0000000000..4754b5b994 --- /dev/null +++ b/modules/storyboard/manifests/cert.pp @@ -0,0 +1,112 @@ +# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. +# +# 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: storyboard::cert +# +# This module sets up the SSL certificate for storyboard, sourcing the content of the +# certificates either from a file or from a string. If included, +# it will be automatically detected within storyboard::application and the +# application will be hosted over https rather than http. +# +class storyboard::cert ( + $ssl_cert_file = undef, + $ssl_cert_content = undef, + $ssl_cert = '/etc/ssl/certs/storyboard.pem', + + $ssl_key_file = undef, + $ssl_key_content = undef, + $ssl_key = '/etc/ssl/private/storyboard.key', + + $ssl_ca_file = undef, + $ssl_ca_content = undef, + $ssl_ca = undef, # '/etc/ssl/certs/ca.pem' +) { + + if $ssl_cert_file != undef { + file { $ssl_cert: + owner => 'root', + group => 'ssl-cert', + mode => '0640', + source => $ssl_cert_file, + before => Class['storyboard::application'], + notify => Class['storyboard::application'], + } + } + elsif $ssl_cert_content != undef { + file { $ssl_cert: + owner => 'root', + group => 'ssl-cert', + mode => '0640', + content => $ssl_cert_content, + before => Class['storyboard::application'], + notify => Class['storyboard::application'], + } + } + else { + fail('When including storyboard::cert, you must define either $ssl_cert_file or $ssl_cert_content') + } + + if $ssl_key_file != undef { + file { $ssl_key: + owner => 'root', + group => 'ssl-cert', + mode => '0640', + source => $ssl_key_file, + before => Class['storyboard::application'], + notify => Class['storyboard::application'], + } + } + elsif $ssl_key_content != undef { + file { $ssl_key: + owner => 'root', + group => 'ssl-cert', + mode => '0640', + content => $ssl_key_content, + before => Class['storyboard::application'], + notify => Class['storyboard::application'], + } + } + else { + fail('When including storyboard::cert, you must define either $ssl_key_file or $ssl_key_content') + } + + # CA file needs special treatment, since we want the path variable + # to be undef in some cases. + if ($ssl_ca_file != undef or $ssl_ca_content != undef) and $ssl_ca == undef { + $resolved_ssl_ca = '/etc/ssl/certs/storyboard.ca.pem' + } else { + $resolved_ssl_ca = $ssl_ca + } + + if $ssl_ca_file != undef { + file { $resolved_ssl_ca: + owner => 'root', + group => 'ssl-cert', + mode => '0640', + source => $ssl_ca_file, + before => Class['storyboard::application'], + notify => Class['storyboard::application'], + } + } + elsif $ssl_ca_content != undef { + file { $resolved_ssl_ca: + owner => 'root', + group => 'ssl-cert', + mode => '0640', + content => $ssl_ca_content, + before => Class['storyboard::application'], + notify => Class['storyboard::application'], + } + } +} \ No newline at end of file diff --git a/modules/storyboard/manifests/init.pp b/modules/storyboard/manifests/init.pp index c492a00389..17cbb925f5 100644 --- a/modules/storyboard/manifests/init.pp +++ b/modules/storyboard/manifests/init.pp @@ -14,234 +14,48 @@ # == Class: storyboard # +# This class will install a fully functional standalone instance of +# storyboard on the current instance. It includes database setup and +# a set of sane configuration defaults. For more precise configuration, +# please use individual submodules. +# class storyboard ( - $vhost_name = $::fqdn, - $mysql_host, - $mysql_password, - $mysql_user, - $projects_file, - $superusers_file, - $ssl_cert_file, - $ssl_key_file, - $ssl_chain_file, - $storyboard_git_source_repo = 'https://git.openstack.org/openstack-infra/storyboard/', - $storyboard_revision = 'master', - $storyboard_webclient_url = 'http://tarballs.openstack.org/storyboard-webclient/storyboard-webclient-latest.tar.gz', - $serveradmin = "webmaster@${::fqdn}", - $ssl_cert_file_contents = '', - $ssl_key_file_contents = '', - $ssl_chain_file_contents = '' + $mysql_database = 'storyboard', + $mysql_user = 'storyboard', + $mysql_user_password = 'changeme', + $hostname = $::fqdn, + $openid_url = 'https://login.launchpad.net/+openid', + + $ssl_cert_file = '/etc/ssl/certs/ssl-cert-snakeoil.pem', + $ssl_cert_content = undef, + $ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil.key', + $ssl_key_content = undef, + $ssl_ca_file = undef, + $ssl_ca_content = undef, ) { - include apache - include mysql::python - include pip - package { 'libapache2-mod-wsgi': - ensure => present, + class { '::storyboard::cert': + ssl_cert_file => $ssl_cert_file, + ssl_cert_content => $ssl_cert_content, + ssl_key_file => $ssl_key_file, + ssl_key_content => $ssl_key_content, + ssl_ca_file => $ssl_ca_file, + ssl_ca_content => $ssl_ca_content, } - package { 'curl': - ensure => present, + class { '::storyboard::mysql': + mysql_database => $mysql_database, + mysql_user => $mysql_user, + mysql_user_password => $mysql_user_password, } - group { 'storyboard': - ensure => present, - } - - user { 'storyboard': - ensure => present, - home => '/home/storyboard', - shell => '/bin/bash', - gid => 'storyboard', - managehome => true, - require => Group['storyboard'], - } - - vcsrepo { '/opt/storyboard': - ensure => latest, - provider => git, - revision => $storyboard_revision, - source => $storyboard_git_source_repo, - } - - exec { 'install-storyboard' : - command => 'pip install /opt/storyboard', - path => '/usr/local/bin:/usr/bin:/bin/', - refreshonly => true, - subscribe => Vcsrepo['/opt/storyboard'], - notify => Service['httpd'], - require => Class['pip'], - } - - file { '/etc/storyboard': - ensure => directory, - } - - file { '/etc/storyboard/storyboard.conf': - ensure => present, - owner => 'storyboard', - mode => '0400', - content => template('storyboard/storyboard.conf.erb'), - notify => Service['httpd'], - require => [ - File['/etc/storyboard'], - User['storyboard'], - ], - } - - file { '/etc/storyboard/projects.yaml': - ensure => present, - owner => 'storyboard', - mode => '0400', - source => $projects_file, - replace => true, - require => [ - File['/etc/storyboard'], - User['storyboard'], - ], - } - - file { '/etc/storyboard/superusers.yaml': - ensure => present, - owner => 'storyboard', - mode => '0400', - source => $superusers_file, - replace => true, - require => [ - File['/etc/storyboard'], - User['storyboard'], - ], - } - - exec { 'migrate-storyboard-db': - command => 'storyboard-db-manage --config-file /etc/storyboard/storyboard.conf upgrade head', - path => '/usr/local/bin:/usr/bin:/bin/', - refreshonly => true, - subscribe => Exec['install-storyboard'], - require => [ - File['/etc/storyboard/storyboard.conf'], - ], - } - - exec { 'load-projects-yaml': - command => 'storyboard-db-manage --config-file /etc/storyboard/storyboard.conf load_projects /etc/storyboard/projects.yaml', - path => '/usr/local/bin:/usr/bin:/bin/', - refreshonly => true, - subscribe => File['/etc/storyboard/projects.yaml'], - require => [ - File['/etc/storyboard/projects.yaml'], - Exec['migrate-storyboard-db'], - ], - } - - exec { 'load-superusers-yaml': - command => 'storyboard-db-manage --config-file /etc/storyboard/storyboard.conf load_superusers /etc/storyboard/superusers.yaml', - path => '/usr/local/bin:/usr/bin:/bin/', - refreshonly => true, - subscribe => File['/etc/storyboard/superusers.yaml'], - require => [ - File['/etc/storyboard/superusers.yaml'], - Exec['migrate-storyboard-db'], - ], - } - - file { '/var/log/storyboard': - ensure => directory, - owner => 'storyboard', - require => User['storyboard'], - } - - # START storyboard-webclient - $tarball = 'storyboard-webclient.tar.gz' - - file { '/var/lib/storyboard': - ensure => directory, - owner => 'storyboard', - group => 'storyboard', - } - - # Checking last modified time versus mtime on the file - exec { 'get-webclient': - command => "curl ${storyboard_webclient_url} -z ./${tarball} -o ${tarball}", - path => '/bin:/usr/bin', - cwd => '/var/lib/storyboard', - onlyif => "curl -I ${storyboard_webclient_url} -z ./${tarball} | grep '200 OK'", - require => [ - File['/var/lib/storyboard'], - Package['curl'], - ] - } - - exec { 'unpack-webclient': - command => "tar -xzf ${tarball}", - path => '/bin:/usr/bin', - cwd => '/var/lib/storyboard', - refreshonly => true, - subscribe => Exec['get-webclient'], - } - - file { '/var/lib/storyboard/www': - ensure => directory, - owner => 'storyboard', - group => 'storyboard', - require => Exec['unpack-webclient'], - source => '/var/lib/storyboard/dist', - recurse => true, - purge => true, - force => true - } - - # END storyboard-webclient - - apache::vhost { $vhost_name: - port => 80, - docroot => 'MEANINGLESS ARGUMENT', - priority => '50', - template => 'storyboard/storyboard.vhost.erb', - require => Package['libapache2-mod-wsgi'], - ssl => true, - } - - a2mod { 'proxy': - ensure => present, - } - - a2mod { 'proxy_http': - ensure => present, - } - - a2mod {'wsgi': - ensure => present, - require => Package['libapache2-mod-wsgi'], - } - - if $ssl_cert_file_contents != '' { - file { $ssl_cert_file: - owner => 'root', - group => 'root', - mode => '0640', - content => $ssl_cert_file_contents, - before => Apache::Vhost[$vhost_name], - } - } - - if $ssl_key_file_contents != '' { - file { $ssl_key_file: - owner => 'root', - group => 'ssl-cert', - mode => '0640', - content => $ssl_key_file_contents, - before => Apache::Vhost[$vhost_name], - } - } - - if $ssl_chain_file_contents != '' { - file { $ssl_chain_file: - owner => 'root', - group => 'root', - mode => '0640', - content => $ssl_chain_file_contents, - before => Apache::Vhost[$vhost_name], - } + class { '::storyboard::application': + hostname => $hostname, + openid_url => $openid_url, + mysql_host => 'localhost', + mysql_port => 3306, + mysql_database => $mysql_database, + mysql_user => $mysql_user, + mysql_user_password => $mysql_user_password, } } diff --git a/modules/storyboard/manifests/load_projects.pp b/modules/storyboard/manifests/load_projects.pp new file mode 100644 index 0000000000..30dd095e41 --- /dev/null +++ b/modules/storyboard/manifests/load_projects.pp @@ -0,0 +1,56 @@ +# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. +# +# 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: storyboard::load_projects +# +# This module will preload a batch of projects into the storyboard database. +# The file should be formatted as yaml, with each entry similar to the +# following: +# +# - project: openstack/storyboard +# description: The StoryBoard API +# use-storyboard: true +# - project: openstack/storyboard-webclient +# description: The StoryBoard HTTP client +# use-storyboard: true +# +class storyboard::load_projects ( + $source, +) { + + include storyboard::params + include storyboard::application + + $project_file_path = '/var/lib/storyboard/projects.yaml' + + file { $project_file_path: + ensure => present, + owner => $storyboard::params::user, + group => $storyboard::params::group, + mode => '0400', + source => $source, + replace => true, + require => [ + Class['storyboard::application'], + ] + } + + exec { 'load-projects-yaml': + command => "storyboard-db-manage --config-file /etc/storyboard.conf load_projects ${project_file_path}", + path => '/usr/local/bin:/usr/bin:/bin/', + refreshonly => true, + subscribe => File[$project_file_path], + require => File[$project_file_path], + } +} \ No newline at end of file diff --git a/modules/storyboard/manifests/load_superusers.pp b/modules/storyboard/manifests/load_superusers.pp new file mode 100644 index 0000000000..68a8d32dc0 --- /dev/null +++ b/modules/storyboard/manifests/load_superusers.pp @@ -0,0 +1,52 @@ +# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. +# +# 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: storyboard::load_superusers +# +# This module will load a batch of superusers into the storyboard database. +# The file should be formatted as yaml, with each entry similar to the +# following: +# +# - openid: https://login.launchpad.net/+id/some_openid +# email: your_email@some_email_host.com +# +class storyboard::load_superusers ( + $source, +) { + + include storyboard::params + include storyboard::application + + $superuser_file_path = '/var/lib/storyboard/superusers.yaml' + + file { $superuser_file_path: + ensure => present, + owner => $storyboard::params::user, + group => $storyboard::params::group, + mode => '0400', + source => $source, + replace => true, + require => [ + Class['storyboard::application'], + ] + } + + exec { 'load-superusers-yaml': + command => "storyboard-db-manage --config-file /etc/storyboard.conf load_superusers ${superuser_file_path}", + path => '/usr/local/bin:/usr/bin:/bin/', + refreshonly => true, + subscribe => File[$superuser_file_path], + require => File[$superuser_file_path], + } +} \ No newline at end of file diff --git a/modules/storyboard/manifests/mysql.pp b/modules/storyboard/manifests/mysql.pp new file mode 100644 index 0000000000..0196a6a45c --- /dev/null +++ b/modules/storyboard/manifests/mysql.pp @@ -0,0 +1,36 @@ +# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. +# +# 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: storyboard::mysql +# +# The StoryBoard MySQL manifest will install a standalone, localhost instance +# of mysql for storyboard to connect to. +# +class storyboard::mysql ( + $mysql_database = 'storyboard', + $mysql_user = 'storyboard', + $mysql_user_password = 'changeme', +) { + + # Install MySQL + include mysql::server + + # Add the storyboard database. + mysql::db { $mysql_database: + user => $mysql_user, + password => $mysql_user_password, + host => 'localhost', + grant => ['all'], + } +} \ No newline at end of file diff --git a/modules/storyboard/manifests/params.pp b/modules/storyboard/manifests/params.pp new file mode 100644 index 0000000000..996548eb3b --- /dev/null +++ b/modules/storyboard/manifests/params.pp @@ -0,0 +1,34 @@ +# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. +# +# 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: storyboard::params +# +# Centralized configuration management for the storyboard module. +# +class storyboard::params () { + + include apache::params + + $user = $apache::params::user + $group = $apache::params::group + + case $::osfamily { + 'Debian': { + # Do nothing, since all the defaults are debian-specific. + } + default: { + fail("Unsupported osfamily: ${::osfamily} The 'storyboard' module only supports osfamily Debian.") + } + } +} diff --git a/modules/storyboard/templates/storyboard.conf.erb b/modules/storyboard/templates/storyboard.conf.erb index 608c0a60b7..7a505e2278 100644 --- a/modules/storyboard/templates/storyboard.conf.erb +++ b/modules/storyboard/templates/storyboard.conf.erb @@ -1,6 +1,87 @@ [DEFAULT] -# 24 hours expiration -token_ttl = 86400 +# Default log level is INFO +# verbose and debug has the same result. +# One of them will set DEBUG log level output +# debug = False +# verbose = False + +# Where to store lock files +lock_path = $state_path/lock + +# log_format = %(asctime)s %(levelname)8s [%(name)s] %(message)s +# log_date_format = %Y-%m-%d %H:%M:%S + +# use_syslog -> syslog +# log_file and log_dir -> log_dir/log_file +# (not log_file) and log_dir -> log_dir/{binary_name}.log +# use_stderr -> stderr +# (not user_stderr) and (not log_file) -> stdout +# publish_errors -> notification system + +# use_syslog = False +# syslog_log_facility = LOG_USER + +# use_stderr = True +# log_file = +# log_dir = + +# publish_errors = False + +# Address to bind the API server +# bind_host = 0.0.0.0 + +# Port the bind the API server to +# bind_port = 8080 + +# OpenId Authentication endpoint +openid_url = <%= @openid_url %> + +# Time in seconds before an access_token expires +access_token_ttl = <%= @access_token_ttl %> + +# Time in seconds before an refresh_token expires +refresh_token_ttl = <%= @refresh_token_ttl %> + +# List paging configuration options. +# page_size_maximum = 500 +# page_size_default = 20 [database] -connection=mysql://<%= mysql_user %>:<%= mysql_password %>@<%= mysql_host %>:3306/storyboard +# This line MUST be changed to actually run storyboard +# Example: +# connection = mysql://root:pass@127.0.0.1:3306/storyboard +# Replace 127.0.0.1 above with the IP address of the database used by the +# main storyboard server. (Leave it as is if the database runs on this host.) +connection=mysql://<%= @mysql_user %>:<%= @mysql_user_password %>@<%= @mysql_host %>:<%= @mysql_port %>/<%= @mysql_database %> + +# The SQLAlchemy connection string used to connect to the slave database +# slave_connection = + +# Database reconnection retry times - in event connectivity is lost +# set to -1 implies an infinite retry count +# max_retries = 10 + +# Database reconnection interval in seconds - if the initial connection to the +# database fails +# retry_interval = 10 + +# Minimum number of SQL connections to keep open in a pool +# min_pool_size = 1 + +# Maximum number of SQL connections to keep open in a pool +# max_pool_size = 10 + +# Timeout in seconds before idle sql connections are reaped +# idle_timeout = 3600 + +# If set, use this value for max_overflow with sqlalchemy +# max_overflow = 20 + +# Verbosity of SQL debugging information. 0=None, 100=Everything +# connection_debug = 0 + +# Add python stack traces to SQL as comment strings +# connection_trace = False + +# If set, use this value for pool_timeout with sqlalchemy +# pool_timeout = 10 diff --git a/modules/storyboard/templates/storyboard.vhost.erb b/modules/storyboard/templates/storyboard.vhost.erb deleted file mode 100644 index 0d3aa8d99c..0000000000 --- a/modules/storyboard/templates/storyboard.vhost.erb +++ /dev/null @@ -1,62 +0,0 @@ -:80> - ServerAdmin <%= scope.lookupvar("storyboard::serveradmin") %> - - ErrorLog ${APACHE_LOG_DIR}/storyboard-error.log - - LogLevel warn - - CustomLog ${APACHE_LOG_DIR}/storyboard-access.log combined - - Redirect / https://<%= scope.lookupvar("storyboard::vhost_name") %>/ - - - - -:443> - ServerName <%= scope.lookupvar("storyboard::vhost_name") %> - ServerAdmin <%= scope.lookupvar("storyboard::serveradmin") %> - - ErrorLog ${APACHE_LOG_DIR}/storyboard-ssl-error.log - - LogLevel warn - - CustomLog ${APACHE_LOG_DIR}/storyboard-ssl-access.log combined - - SSLEngine on - - SSLCertificateFile <%= scope.lookupvar("storyboard::ssl_cert_file") %> - SSLCertificateKeyFile <%= scope.lookupvar("storyboard::ssl_key_file") %> -<% if scope.lookupvar("storyboard::ssl_chain_file") != "" %> - SSLCertificateChainFile <%= scope.lookupvar("storyboard::ssl_chain_file") %> -<% end %> - - - SSLOptions +StdEnvVars - - - SSLOptions +StdEnvVars - - - BrowserMatch "MSIE [2-6]" \ - nokeepalive ssl-unclean-shutdown \ - downgrade-1.0 force-response-1.0 - # MSIE 7 and newer should be able to use keepalive - BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown - - DocumentRoot /var/lib/storyboard/www - - WSGIDaemonProcess storyboard user=storyboard group=storyboard threads=5 python-path=/usr/local/lib/python2.7/dist-packages - WSGIScriptAlias /api /usr/local/lib/python2.7/dist-packages/storyboard/api/app.wsgi - WSGIPassAuthorization On - - # The app.wsgi file has to be accessible by apache. It won't - # be visible to clients because of the DocumentRoot though. - - WSGIProcessGroup storyboard - WSGIApplicationGroup %{GLOBAL} - Order deny,allow - Allow from all - - - - diff --git a/modules/storyboard/templates/storyboard_http.vhost.erb b/modules/storyboard/templates/storyboard_http.vhost.erb new file mode 100644 index 0000000000..d4c89234f2 --- /dev/null +++ b/modules/storyboard/templates/storyboard_http.vhost.erb @@ -0,0 +1,17 @@ +:80> +<% if scope.lookupvar("storyboard::application::serveradmin") %> + ServerAdmin <%= scope.lookupvar("storyboard::application::serveradmin") %> +<% end %> + ServerName <%= scope.lookupvar("storyboard::application::hostname") %> + + DocumentRoot <%= scope.lookupvar("storyboard::application::www_root") %> + + WSGIDaemonProcess storyboard user=<%= scope.lookupvar("storyboard::params::user") %> group=<%= scope.lookupvar("storyboard::params::group") %> threads=5 python-path=/usr/local/lib/python2.7/dist-packages + WSGIScriptAlias /api /var/lib/storyboard/storyboard.wsgi + WSGIPassAuthorization On + + LogLevel warn + ErrorLog ${APACHE_LOG_DIR}/storyboard-error.log + CustomLog ${APACHE_LOG_DIR}/storyboard-access.log combined + + \ No newline at end of file diff --git a/modules/storyboard/templates/storyboard_https.vhost.erb b/modules/storyboard/templates/storyboard_https.vhost.erb new file mode 100644 index 0000000000..5e9e79386d --- /dev/null +++ b/modules/storyboard/templates/storyboard_https.vhost.erb @@ -0,0 +1,54 @@ +:80> +<% if (scope.lookupvar("storyboard::application::serveradmin") != :undefined) %> + ServerAdmin <%= scope.lookupvar("storyboard::application::serveradmin") %> +<% end %> + ServerName <%= scope.lookupvar("storyboard::application::hostname") %> + + DocumentRoot <%= scope.lookupvar("storyboard::application::www_root") %> + + Redirect / https://<%= scope.lookupvar("storyboard::application::hostname") %>/ + + LogLevel warn + ErrorLog ${APACHE_LOG_DIR}/storyboard-error.log + CustomLog ${APACHE_LOG_DIR}/storyboard-access.log combined + + + + :443> + <% if (scope.lookupvar("storyboard::application::serveradmin") != :undefined) %> + ServerAdmin <%= scope.lookupvar("storyboard::application::serveradmin") %> + <% end %> + ServerName <%= scope.lookupvar("storyboard::application::hostname") %> + + LogLevel warn + ErrorLog ${APACHE_LOG_DIR}/storyboard-ssl-error.log + CustomLog ${APACHE_LOG_DIR}/storyboard-ssl-access.log combined + + SSLEngine on + + SSLCertificateFile <%= scope.lookupvar("storyboard::cert::ssl_cert") %> + SSLCertificateKeyFile <%= scope.lookupvar("storyboard::cert::ssl_key") %> + <% if scope.lookupvar("storyboard::cert::ssl_ca") != :undef %> + SSLCertificateChainFile <%= scope.lookupvar("storyboard::cert::ssl_ca") %> + <% end %> + + + SSLOptions +StdEnvVars + + + SSLOptions +StdEnvVars + + + BrowserMatch "MSIE [2-6]" \ + nokeepalive ssl-unclean-shutdown \ + downgrade-1.0 force-response-1.0 + # MSIE 7 and newer should be able to use keepalive + BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown + + DocumentRoot <%= scope.lookupvar("storyboard::application::www_root") %> + + WSGIDaemonProcess storyboard user=<%= scope.lookupvar("storyboard::params::user") %> group=<%= scope.lookupvar("storyboard::params::group") %> threads=5 python-path=/usr/local/lib/python2.7/dist-packages + WSGIScriptAlias /api /var/lib/storyboard/storyboard.wsgi + WSGIPassAuthorization On + +