Dduvall has submitted this change and it was merged.
Change subject: Add Vagrant role for Sentry (server + MW extension)
......................................................................
Add Vagrant role for Sentry (server + MW extension)
Bug: T84957
Change-Id: Ibfd70d3df9aee99f617013e369965fb5f4227bbd
---
M puppet/hieradata/common.yaml
A puppet/modules/role/manifests/sentry.pp
A puppet/modules/sentry/manifests/init.pp
A puppet/modules/sentry/templates/apache-site.erb
A puppet/modules/sentry/templates/sentry.conf.py.erb
A puppet/modules/sentry/templates/sentry_create_project.py.erb
A puppet/modules/sentry/templates/upstart.erb
A puppet/modules/virtualenv/manifests/environment.pp
A puppet/modules/virtualenv/manifests/init.pp
9 files changed, 372 insertions(+), 0 deletions(-)
Approvals:
Dduvall: Looks good to me, approved
Gergő Tisza: Looks good to me, but someone else must approve
diff --git a/puppet/hieradata/common.yaml b/puppet/hieradata/common.yaml
index f3c6a31..2ff3d5c 100644
--- a/puppet/hieradata/common.yaml
+++ b/puppet/hieradata/common.yaml
@@ -166,6 +166,8 @@
role::mediawiki::hostname: 127.0.0.1
+role::sentry::dsn: "%{hiera('sentry::dsn_file')}"
+
scholarships::vhost_name: scholarships.local.wmftest.net
scholarships::db_name: scholarships
scholarships::db_user: scholarships
@@ -174,4 +176,18 @@
scholarships::cache_dir: /var/cache/scholarships
scholarships::log_file: /vagrant/logs/scholarships.log
+sentry::user: sentry
+sentry::group: sentry
+sentry::db_name: sentry
+sentry::db_user: sentry
+sentry::db_pass: vagrant
+sentry::vhost_name: sentry.local.wmftest.net
+sentry::deploy_dir: /srv/sentry
+sentry::cfg_file: /etc/sentry.conf.py
+sentry::mail_log_file: /vagrant/logs/sentry.mail.log
+sentry::secret_key: s0F2ybS8jPLvzadqVudo7VykVWT1JO9FoErhc6gkJj6/KNWeFUbUiQ==
+sentry::dsn_file: /srv/sentry/sentry_dsn.txt
+sentry::admin_user: admin
+sentry::admin_pass: vagrant
+
smtplog::log_file: /vagrant/logs/smtp.log
diff --git a/puppet/modules/role/manifests/sentry.pp
b/puppet/modules/role/manifests/sentry.pp
new file mode 100644
index 0000000..e44f213
--- /dev/null
+++ b/puppet/modules/role/manifests/sentry.pp
@@ -0,0 +1,20 @@
+# == Class: role::sentry
+# Installs a Sentry instance which collects errors from your wiki
+#
+# [*dsn*]
+# The Sentry DSN to use, see
+# http://raven.readthedocs.org/en/latest/config/#the-sentry-dsn
+#
+class role::sentry (
+ $dsn,
+) {
+ include ::sentry
+
+ mediawiki::extension { 'Sentry':
+ settings => [
+ # OMG that's ugly. Did not find a better way to reuse
+ # the output of a script.
+ "\$wgSentryDsn = file_get_contents('${dsn}');",
+ ],
+ }
+}
diff --git a/puppet/modules/sentry/manifests/init.pp
b/puppet/modules/sentry/manifests/init.pp
new file mode 100644
index 0000000..ac40d20
--- /dev/null
+++ b/puppet/modules/sentry/manifests/init.pp
@@ -0,0 +1,154 @@
+# == Class: sentry
+#
+# This Puppet class installs and configures a Sentry instance -an
+# error aggregator and dashboard which can be used to view and
+# organize MediaWiki PHP and JS errors.
+#
+# === Parameters
+#
+# [*user*]
+# System user with which to run Sentry.
+#
+# [*group*]
+# System group with which to run Sentry.
+#
+# [*db_name*]
+# Logical MySQL database name (example: 'sentry').
+#
+# [*db_user*]
+# MySQL user to use to connect to the database (example: 'wikidb').
+#
+# [*db_pass*]
+# Password for MySQL account (example: 'secret123').
+#
+# [*vhost_name*]
+# Hostname of the Sentry server (example: 'sentry.local.wmftest.net').
+#
+# [*deploy_dir*]
+# Path where Sentry should be installed (example: '/var/sentry').
+#
+# [*cfg_file*]
+# Sentry configuration file. Needs to end in '.py'. (example:
'/etc/sentry.conf.py')
+# The file will be generated by puppet.
+#
+# [*mail_log_file*]
+# File to to write mails which would be sent (example:
'/vagrant/logs/sentry.mail.log').
+#
+# [*secret_key*]
+# The secret key required by Sentry.
+#
+# [*dsn_file*]
+# A text file which will store the DSN to the default group. Clients will
+# need to send logs to this URL. (example: '/var/sentry/sentry_dsn.txt')
+#
+# [*admin_user*]
+# Username of the Sentry superuser. (example: 'admin')
+#
+# [*admin_pass*]
+# Password of the Sentry superuser. (example: 'vagrant')
+#
+class sentry (
+ $user,
+ $group,
+ $db_name,
+ $db_user,
+ $db_pass,
+ $vhost_name,
+ $deploy_dir,
+ $cfg_file,
+ $mail_log_file,
+ $secret_key,
+ $dsn_file,
+ $admin_user,
+ $admin_pass,
+) {
+ include ::apache::mod::proxy
+ include ::apache::mod::proxy_http
+ include ::apache::mod::headers
+ include ::php
+ require ::mysql
+ require ::virtualenv
+
+ #
http://stackoverflow.com/questions/5178292/pip-install-mysql-python-fails-with-environmenterror-mysql-config-not-found
+ require_package('libmysqlclient-dev')
+ # needed for building the python package lxml
+ require_package('libxml2-dev', 'libxslt1-dev')
+
+ $sentry_cli = "${deploy_dir}/bin/sentry --config='${cfg_file}'"
+ $sentry_create_project_script =
"${deploy_dir}/bin/sentry_create_project.py"
+
+ user { $user:
+ ensure => present,
+ gid => $group,
+ shell => '/bin/false',
+ home => '/nonexistent',
+ system => true,
+ }
+
+ group { $group:
+ ensure => present,
+ system => true,
+ }
+
+ # Use virtualenv because Sentry has lots of dependencies
+ virtualenv::environment { $deploy_dir:
+ ensure => present,
+ packages => ['sentry[mysql]==7.*'],
+ require => Package['libmysqlclient-dev'],
+ }
+
+ mysql::db { $db_name:
+ ensure => present,
+ }
+
+ mysql::user { $db_user:
+ ensure => present,
+ grant => "ALL ON ${db_name}.*",
+ password => $db_pass,
+ require => Mysql::Db[$db_name],
+ }
+
+ apache::site { 'sentry':
+ ensure => present,
+ content => template('sentry/apache-site.erb'),
+ require => Class['::apache::mod::proxy', '::apache::mod::proxy_http',
'::apache::mod::headers'],
+ }
+
+ file { $cfg_file:
+ ensure => present,
+ group => $group,
+ content => template('sentry/sentry.conf.py.erb'),
+ mode => 0640,
+ }
+
+ exec { 'initialize sentry database':
+ command => "${sentry_cli} upgrade",
+ require => [Virtualenv::Environment[$deploy_dir],
Mysql::User[$db_user], File[$cfg_file]],
+ }
+
+ file { $sentry_create_project_script:
+ ensure => present,
+ content => template('sentry/sentry_create_project.py.erb'),
+ mode => '755',
+ require => Virtualenv::Environment[$deploy_dir],
+ }
+
+ exec { 'create sentry project':
+ command => "${deploy_dir}/bin/python ${sentry_create_project_script}",
+ creates => $dsn_file,
+ require => [Exec['initialize sentry database'],
File[$sentry_create_project_script]],
+ }
+
+ file { '/etc/init/sentry.conf':
+ ensure => present,
+ content => template('sentry/upstart.erb'),
+ mode => '0444',
+ }
+
+ service { 'sentry':
+ ensure => running,
+ provider => 'upstart',
+ require => [Virtualenv::Environment[$deploy_dir],
Mysql::User[$db_user]],
+ subscribe => [File[$cfg_file], Exec['create sentry project']],
+ }
+}
diff --git a/puppet/modules/sentry/templates/apache-site.erb
b/puppet/modules/sentry/templates/apache-site.erb
new file mode 100644
index 0000000..ea9fef2
--- /dev/null
+++ b/puppet/modules/sentry/templates/apache-site.erb
@@ -0,0 +1,10 @@
+#####################################################################
+### THIS FILE IS MANAGED BY PUPPET
+#####################################################################
+
+ServerName <%= @vhost_name %>
+
+ProxyPass / http://localhost:9002/
+ProxyPassReverse / http://localhost:9002/
+ProxyPreserveHost On
+RequestHeader set X-Forwarded-Proto "https" env=HTTPS
diff --git a/puppet/modules/sentry/templates/sentry.conf.py.erb
b/puppet/modules/sentry/templates/sentry.conf.py.erb
new file mode 100644
index 0000000..50b9565
--- /dev/null
+++ b/puppet/modules/sentry/templates/sentry.conf.py.erb
@@ -0,0 +1,54 @@
+#####################################################################
+### THIS FILE IS MANAGED BY PUPPET
+#####################################################################
+
+from sentry.conf.server import *
+
+import os.path
+
+CONF_ROOT = os.path.dirname(__file__)
+
+################
+## Database ##
+################
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.mysql',
+ 'NAME': '<%= @db_name %>',
+ 'USER': '<%= @db_user %>',
+ 'PASSWORD': '<%= @db_pass %>',
+ }
+}
+
+################
+## Web Server ##
+################
+
+SENTRY_URL_PREFIX = 'http://<%= @vhost_name %>:<%= scope['::forwarded_port']
%>'
+
+SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
+USE_X_FORWARDED_HOST = True
+
+SENTRY_ALLOW_ORIGIN = '*'
+
+SENTRY_WEB_HOST = '0.0.0.0'
+SENTRY_WEB_PORT = 9002 # 9000 is PHP-FVM, 9001 is Xdebug proxy
+SENTRY_WEB_OPTIONS = {
+ 'limit_request_line': 0, # required for raven-js
+ 'secure_scheme_headers': {'X-FORWARDED-PROTO': 'https'},
+}
+
+#################
+## Mail Server ##
+#################
+
+EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
+EMAIL_FILE_PATH = '<%= @mail_log_file %>'
+SERVER_EMAIL = 'sentry@<%= @vhost_name %>'
+
+###########
+## etc. ##
+###########
+
+SECRET_KEY = '<%= @secret_key %>'
diff --git a/puppet/modules/sentry/templates/sentry_create_project.py.erb
b/puppet/modules/sentry/templates/sentry_create_project.py.erb
new file mode 100644
index 0000000..82611a5
--- /dev/null
+++ b/puppet/modules/sentry/templates/sentry_create_project.py.erb
@@ -0,0 +1,33 @@
+# based on http://sentry.readthedocs.org/en/latest/faq/index.html#how-do-i
+from sentry.utils.runner import configure
+configure('<%= @cfg_file %>')
+
+from sentry.models import User, Organization, Team, Project, ProjectKey
+
+user = User()
+user.username = '<%= @admin_user %>'
+user.email = 'admin@<%= @vhost_name %>'
+user.is_superuser = True
+user.set_password('<%= @admin_pass %>')
+user.save()
+
+organization = Organization()
+organization.name = 'MediaWiki'
+organization.owner = user
+organization.save()
+
+team = Team()
+team.name = 'Sentry'
+team.organization = organization
+team.owner = user
+team.save()
+
+project = Project()
+project.team = team
+project.name = 'Default'
+project.organization = organization
+project.save()
+
+key = ProjectKey.objects.filter(project=project)[0]
+with open('<%= @dsn_file %>', 'w+') as f:
+ f.write(key.dsn_public)
diff --git a/puppet/modules/sentry/templates/upstart.erb
b/puppet/modules/sentry/templates/upstart.erb
new file mode 100644
index 0000000..0fc95a8
--- /dev/null
+++ b/puppet/modules/sentry/templates/upstart.erb
@@ -0,0 +1,12 @@
+#####################################################################
+### THIS FILE IS MANAGED BY PUPPET
+#####################################################################
+
+description "Sentry error log tracker"
+
+start on startup
+
+exec /sbin/start-stop-daemon --quiet --start \
+ --chuid '<%= @user %>:<%= @group %>' \
+ --make-pidfile --pidfile /var/run/sentry.pid \
+ --startas '<%= @deploy_dir %>/bin/sentry' -- --config='<%= @cfg_file %>'
start
diff --git a/puppet/modules/virtualenv/manifests/environment.pp
b/puppet/modules/virtualenv/manifests/environment.pp
new file mode 100644
index 0000000..d69dca6
--- /dev/null
+++ b/puppet/modules/virtualenv/manifests/environment.pp
@@ -0,0 +1,62 @@
+# == Class virtualenv
+# Helper class to install python packages via virtualenv.
+# Will create a virtualenv directory with the given packages.
+#
+# This is a nasty hack which does not use package providers
+# as puppet does not suppose using those with virtualenv:
+# https://tickets.puppetlabs.com/browse/PUP-1062
+#
+# === Parameters
+#
+# [*ensure*]
+# 'present' to create the environment, 'absent' to delete
+# it (along with all contents, whether puppet-managed or not)
+#
+# [*dir*]
+# The directory where the virtual environment should be.
+# Will be created if it does not exist.
+#
+# [*packages*]
+# An array of pip packages to install. Must not be empty.
+#
+# [*owner*]
+# User owner of the environment directory and created files.
+#
+# [*group*]
+# Group owner of the environment directory and created files.
+#
+define virtualenv::environment (
+ $packages,
+ $dir = $title,
+ $ensure = 'present',
+ $owner = 'root',
+ $group = 'root',
+) {
+ require virtualenv
+
+ if $ensure == 'present' {
+ file { $dir:
+ ensure => directory,
+ owner => $owner,
+ group => $group,
+ }
+
+ exec { "virtualenv-${dir}":
+ command => join(["virtualenv . && ./bin/pip install '",
join($packages, "' '"), "'"]),
+ cwd => $dir,
+ creates => "${dir}/lib",
+ user => $owner,
+ group => $group,
+ require => File[$dir],
+ }
+ } elsif $ensure == 'absent' {
+ file { $dir:
+ ensure => absent,
+ force => true,
+ recurse => true,
+ purge => true,
+ }
+ }
+}
+
+
diff --git a/puppet/modules/virtualenv/manifests/init.pp
b/puppet/modules/virtualenv/manifests/init.pp
new file mode 100644
index 0000000..7da6f22
--- /dev/null
+++ b/puppet/modules/virtualenv/manifests/init.pp
@@ -0,0 +1,11 @@
+# == Class virtualenv
+# Helper class to install python packages via virtualenv.
+# Require this class, then use virtualenv::environment.
+#
+class virtualenv {
+ package { 'virtualenv':
+ ensure => present,
+ provider => pip,
+ }
+}
+
--
To view, visit https://gerrit.wikimedia.org/r/181606
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ibfd70d3df9aee99f617013e369965fb5f4227bbd
Gerrit-PatchSet: 8
Gerrit-Project: mediawiki/vagrant
Gerrit-Branch: master
Gerrit-Owner: Gergő Tisza <[email protected]>
Gerrit-Reviewer: BryanDavis <[email protected]>
Gerrit-Reviewer: Dduvall <[email protected]>
Gerrit-Reviewer: Gergő Tisza <[email protected]>
Gerrit-Reviewer: Gilles <[email protected]>
Gerrit-Reviewer: Ori.livneh <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits