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

Reply via email to