Browse Source

Initial commit.

feature/python-error-tracking
Drew Larson 8 years ago
commit
b6ad0dd068
  1. 7
      .gitignore
  2. 33
      README.md
  3. 53
      Vagrantfile
  4. 7
      bikeshop_project/.coveragerc
  5. 0
      bikeshop_project/bikeshop/__init__.py
  6. 0
      bikeshop_project/bikeshop/settings/__init__.py
  7. 117
      bikeshop_project/bikeshop/settings/base.py
  8. 47
      bikeshop_project/bikeshop/settings/development.py
  9. 21
      bikeshop_project/bikeshop/urls.py
  10. 16
      bikeshop_project/bikeshop/wsgi.py
  11. 0
      bikeshop_project/core/__init__.py
  12. 3
      bikeshop_project/core/admin.py
  13. 5
      bikeshop_project/core/apps.py
  14. 35
      bikeshop_project/core/migrations/0001_initial.py
  15. 25
      bikeshop_project/core/migrations/0002_payment.py
  16. 27
      bikeshop_project/core/migrations/0003_visit.py
  17. 0
      bikeshop_project/core/migrations/__init__.py
  18. 49
      bikeshop_project/core/models.py
  19. 3
      bikeshop_project/core/tests.py
  20. 3
      bikeshop_project/core/views.py
  21. 10
      bikeshop_project/manage.py
  22. 0
      bikeshop_project/registration/__init__.py
  23. 3
      bikeshop_project/registration/admin.py
  24. 5
      bikeshop_project/registration/apps.py
  25. 49
      bikeshop_project/registration/migrations/0001_initial.py
  26. 0
      bikeshop_project/registration/migrations/__init__.py
  27. 87
      bikeshop_project/registration/models.py
  28. 3
      bikeshop_project/registration/tests.py
  29. 3
      bikeshop_project/registration/views.py
  30. 11
      package.json
  31. 14
      provision/group_vars/all
  32. 11
      provision/group_vars/production/non-secrets.yml
  33. 10
      provision/group_vars/production/secrets.yml
  34. 10
      provision/group_vars/staging/non-secrets.yml
  35. 2
      provision/group_vars/staging/secrets.yml
  36. 5
      provision/inventories/production
  37. 3
      provision/roles/app/tasks/main.yml
  38. 5
      provision/roles/app/tasks/prepare.yml
  39. 15
      provision/roles/app/tasks/virtualenv.yml
  40. 2
      provision/roles/app/templates/sparse-checkout
  41. 22
      provision/roles/common/tasks/main.yml
  42. 18
      provision/roles/database/tasks/main.yml
  43. 36
      provision/roles/deploy-code/tasks/main.yml
  44. 14
      provision/roles/django/tasks/main.yml
  45. 3
      provision/roles/handlers/main.yml
  46. 2
      provision/roles/nginx/handlers/main.yml
  47. 12
      provision/roles/nginx/tasks/main.yml
  48. 61
      provision/roles/nginx/templates/production/nginx-site.conf
  49. 31
      provision/roles/nginx/templates/staging/nginx-site.conf
  50. 14
      provision/roles/python/tasks/main.yml
  51. 3
      provision/roles/supervisor/handlers/main.yml
  52. 12
      provision/roles/supervisor/tasks/main.yml
  53. 4
      provision/roles/supervisor/tasks/staging/main.yml
  54. 45
      provision/roles/supervisor/templates/production/supervisor-program.conf
  55. 10
      provision/roles/supervisor/templates/staging/supervisor-program.conf
  56. 4
      provision/roles/tasks/main.yml
  57. 4
      provision/roles/tasks/staging/main.yml
  58. 11
      provision/roles/templates/production/supervisor-program.conf
  59. 10
      provision/roles/templates/staging/supervisor-program.conf
  60. 1
      provision/roles/zenoamaro.postgresql/.gitignore
  61. 28
      provision/roles/zenoamaro.postgresql/.travis.yml
  62. 21
      provision/roles/zenoamaro.postgresql/LICENSE.md
  63. 117
      provision/roles/zenoamaro.postgresql/README.md
  64. 62
      provision/roles/zenoamaro.postgresql/Vagrantfile
  65. 26
      provision/roles/zenoamaro.postgresql/boxed.yml
  66. 606
      provision/roles/zenoamaro.postgresql/defaults/main.yml
  67. 8
      provision/roles/zenoamaro.postgresql/handlers/main.yml
  68. 19
      provision/roles/zenoamaro.postgresql/inventory
  69. 19
      provision/roles/zenoamaro.postgresql/main.yml
  70. 1
      provision/roles/zenoamaro.postgresql/meta/.galaxy_install_info
  71. 21
      provision/roles/zenoamaro.postgresql/meta/main.yml
  72. 55
      provision/roles/zenoamaro.postgresql/tasks/configure.yml
  73. 49
      provision/roles/zenoamaro.postgresql/tasks/extensions.yml
  74. 51
      provision/roles/zenoamaro.postgresql/tasks/install.yml
  75. 5
      provision/roles/zenoamaro.postgresql/tasks/main.yml
  76. 11
      provision/roles/zenoamaro.postgresql/templates/environment
  77. 5
      provision/roles/zenoamaro.postgresql/templates/pg_ctl.conf
  78. 112
      provision/roles/zenoamaro.postgresql/templates/pg_hba.conf
  79. 46
      provision/roles/zenoamaro.postgresql/templates/pg_ident.conf
  80. 530
      provision/roles/zenoamaro.postgresql/templates/postgresql.conf
  81. 24
      provision/roles/zenoamaro.postgresql/test.yml
  82. 1
      provision/site.retry
  83. 18
      provision/site.yml
  84. 18
      provision/templates/humans.txt
  85. 3
      provision/templates/pg_hba.conf
  86. 8
      requirements/base.txt
  87. 4
      requirements/development.txt
  88. 2
      requirements/production.txt
  89. 1
      requirements/staging.txt
  90. 2
      requirements/testing.txt

7
.gitignore

@ -0,0 +1,7 @@
.DS_Store
.vagrant
.idea
*.pyc
trailersafeguard_project/db.sqlite3
trailersafeguard_project/static
trailersafeguard_project/celerybeat.pid

33
README.md

@ -0,0 +1,33 @@
## Quickstart
Maybe this isn't such a quick start, but it's the best I have right now. After the following steps are completed, you will have a working development version of the Trailer-Safeguard Django application connectable on [bikeshop-dev.local:8000/](http://bikeshop-dev.local:8000/).
1. Make sure Virtualbox is installed and updated
2. Make sure Vagrant is installed and updated
3. Verify *pip* is installed `which pip`
4. Verify *ansible* is installed `which ansible`
5. Clone source `git clone AHHHHHH`
6. `ansible-galaxy install zenoamaro.postgresql -p provision/roles`
7. `vagrant plugin install vagrant-hostsupdater`
8. `vagrant up`
9. `vagrant ssh`
10. `cd /srv/bikeshop && . /opt/venv/bikeshop_development/bin/activate`
11. `./manage.py migrate`
12. `./manage.py loaddata core/migrations/initial_data.yaml && ./manage.py loaddata authentication/migrations/initial_data.yaml`
13. `./manage.py runserver 0.0.0.0:8000`
### Example of dumpdata command
./manage.py dumpdata --exclude=auth --exclude=contenttypes --exclude=incoming --format=yaml
### Reset the Postgres DB
1. `vagrant ssh`
2. `sudo -i -u postgres`
3. `psql`
4. `\c trailersafeguard_development`
5. ```
DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
COMMENT ON SCHEMA public IS 'standard public schema';
```
6. Steps 11 and 12 from **Quickstart**.

53
Vagrantfile

@ -0,0 +1,53 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# All Vagrant configuration is done here. The most common configuration
# options are documented and commented below. For a complete reference,
# please see the online documentation at vagrantup.com.
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "ubuntu/trusty64"
config.vm.hostname = "bikeshop-dev"
config.vm.provider "virtualbox" do |v|
v.name = "bikeshop-dev"
v.memory = 1024
end
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# config.vm.network "forwarded_port", guest: 8000, host: 80
# Create a private network, which allows host-only access to the machine
# using a specific IP.
config.vm.network "private_network", ip: "192.168.33.45"
config.vm.hostname = "bikeshop.local"
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
config.vm.synced_folder '.', '/vagrant', disabled: true
config.vm.synced_folder "bikeshop_project", "/srv/bikeshop", type: "nfs"
config.vm.provision "ansible" do |ansible|
ansible.groups = {
"development" => "default"
}
ansible.playbook = "provision/site.yml"
# ansible.ask_sudo_pass = true
# ansible.verbose = "v"
ansible.sudo = true
ansible.host_key_checking = false
ansible.limit = "default"
ansible.extra_vars = {
ansible_ssh_user: 'vagrant',
ansible_connection: 'ssh',
ansible_ssh_args: '-o ForwardAgent=yes',
}
end
end

7
bikeshop_project/.coveragerc

@ -0,0 +1,7 @@
[report]
exclude_lines =
prama: no cover
def __repr__
def __str__

0
bikeshop_project/bikeshop/__init__.py

0
bikeshop_project/bikeshop/settings/__init__.py

117
bikeshop_project/bikeshop/settings/base.py

@ -0,0 +1,117 @@
"""
Django settings for bikeshop project.
Generated by 'django-admin startproject' using Django 1.9.4.
For more information on this file, see
https://docs.djangoproject.com/en/1.9/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.9/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'registration',
'core',
]
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'bikeshop.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'bikeshop.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/1.9/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/
STATIC_URL = '/static/'
AUTH_USER_MODEL = 'registration.Member'

47
bikeshop_project/bikeshop/settings/development.py

@ -0,0 +1,47 @@
from .base import *
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = ')8(+b48*njk+e^8-l!6s3k4d=z(#g$v=)i^=_p-l*#-kk=!v_d'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'bikeshop_development',
'USER': 'bikeshop',
'PASSWORD': 'password',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'verbose'
},
},
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(pathname)s %(message)s'
},
},
'loggers': {
'django': {
'handlers': ['console'],
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
},
'bikeshop': {
'handlers': ['console'],
'level': os.getenv('DJANGO_LOG_LEVEL', 'DEBUG'),
}
},
}

21
bikeshop_project/bikeshop/urls.py

@ -0,0 +1,21 @@
"""bikeshop URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.9/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
]

16
bikeshop_project/bikeshop/wsgi.py

@ -0,0 +1,16 @@
"""
WSGI config for bikeshop project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "bikeshop.settings")
application = get_wsgi_application()

0
bikeshop_project/core/__init__.py

3
bikeshop_project/core/admin.py

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

5
bikeshop_project/core/apps.py

@ -0,0 +1,5 @@
from django.apps import AppConfig
class CoreConfig(AppConfig):
name = 'core'

35
bikeshop_project/core/migrations/0001_initial.py

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2016-03-23 02:01
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Membership',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('modified_at', models.DateTimeField(auto_now=True)),
('renewed_at', models.DateTimeField(default=django.utils.timezone.now)),
('safe_space', models.BooleanField(default=False)),
('community', models.BooleanField(default=False)),
('space', models.BooleanField(default=False)),
('give_back', models.BooleanField(default=False)),
('acknowledgement', models.BooleanField(default=False)),
('member', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='membership', to=settings.AUTH_USER_MODEL)),
],
),
]

25
bikeshop_project/core/migrations/0002_payment.py

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2016-03-23 02:27
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('core', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Payment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('type', models.CharField(choices=[('CASH', 'cash'), ('CHEQUE', 'cheque'), ('VOLUNTEERING', 'volunteering'), ('STRIPE', 'stripe'), ('PAYPAL', 'paypal')], max_length=12)),
('created_at', models.DateTimeField(auto_now_add=True)),
('membership', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.Membership')),
],
),
]

27
bikeshop_project/core/migrations/0003_visit.py

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2016-03-23 02:34
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('core', '0002_payment'),
]
operations = [
migrations.CreateModel(
name='Visit',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('purpose', models.CharField(choices=[('VOLUNTEER', 'volunteer'), ('WORK', 'work on bike'), ('WORKSHOP', 'workshop')], max_length=50)),
('member', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]

0
bikeshop_project/core/migrations/__init__.py

49
bikeshop_project/core/models.py

@ -0,0 +1,49 @@
from django.db import models
from django.utils import timezone
class Membership(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
renewed_at = models.DateTimeField(default=timezone.now)
member = models.OneToOneField(
'registration.Member',
on_delete=models.CASCADE,
related_name='membership'
)
safe_space = models.BooleanField(default=False)
community = models.BooleanField(default=False)
space = models.BooleanField(default=False)
give_back = models.BooleanField(default=False)
# this should be a form field that requires the new member to type out there full name
acknowledgement = models.BooleanField(default=False)
class Payment(models.Model):
membership = models.ForeignKey(
'Membership',
on_delete=models.CASCADE,
)
payment_choices = (
('CASH', 'cash'),
('CHEQUE', 'cheque'),
('VOLUNTEERING', 'volunteering'),
('STRIPE', 'stripe'),
('PAYPAL', 'paypal')
)
type = models.CharField(max_length=12, choices=payment_choices)
created_at = models.DateTimeField(auto_now_add=True)
class Visit(models.Model):
visit_choices = (
('VOLUNTEER', 'volunteer'),
('WORK', 'work on bike'),
('WORKSHOP', 'workshop')
)
member = models.ForeignKey(
'registration.Member',
on_delete=models.CASCADE
)
created_at = models.DateTimeField(auto_now_add=True)
purpose = models.CharField(max_length=50, choices=visit_choices)

3
bikeshop_project/core/tests.py

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

3
bikeshop_project/core/views.py

@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.

10
bikeshop_project/manage.py

@ -0,0 +1,10 @@
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "bikeshop.settings.development")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)

0
bikeshop_project/registration/__init__.py

3
bikeshop_project/registration/admin.py

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

5
bikeshop_project/registration/apps.py

@ -0,0 +1,5 @@
from django.apps import AppConfig
class RegistrationConfig(AppConfig):
name = 'registration'

49
bikeshop_project/registration/migrations/0001_initial.py

@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2016-03-23 01:25
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0007_alter_validators_add_error_messages'),
]
operations = [
migrations.CreateModel(
name='Member',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('email', models.EmailField(max_length=255, unique=True, verbose_name='email address')),
('first_name', models.CharField(max_length=255)),
('last_name', models.CharField(max_length=255)),
('preferred_name', models.CharField(blank=True, max_length=255, null=True)),
('date_of_birth', models.DateField(blank=True, null=True)),
('guardian_name', models.CharField(blank=True, max_length=255, null=True)),
('phone', models.CharField(blank=True, max_length=20, null=True)),
('street', models.CharField(blank=True, max_length=255, null=True)),
('city', models.CharField(blank=True, max_length=255, null=True)),
('province', models.CharField(blank=True, max_length=255, null=True)),
('country', models.CharField(blank=True, max_length=255, null=True)),
('post_code', models.CharField(blank=True, max_length=20, null=True)),
('self_identification', models.CharField(blank=True, max_length=255, null=True)),
('gender', models.CharField(blank=True, max_length=255, null=True)),
('involvement', models.CharField(blank=True, max_length=255, null=True)),
('waiver', models.DateTimeField(blank=True, null=True)),
('is_active', models.BooleanField(default=True)),
('is_admin', models.BooleanField(default=False)),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
],
options={
'abstract': False,
},
),
]

0
bikeshop_project/registration/migrations/__init__.py

87
bikeshop_project/registration/models.py

@ -0,0 +1,87 @@
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models
class CustomMemberManager(BaseUserManager):
def create_user(self, email, first_name, last_name, password=None):
"""
Creates and saves a User with the given email and password.
:param email: str
:param password: str
:param first_name: str
:param last_name: str
:return: object `CustomUser`
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
:param email: str
:param password: str
:return: object `CustomUser`
"""
user = self.create_user(email, password=password)
user.is_admin = True
user.is_superuser = True
user.save(using=self._db)
return user
class Member(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
first_name = models.CharField(max_length=255, null=False)
last_name = models.CharField(max_length=255, null=False)
preferred_name = models.CharField(max_length=255, null=True, blank=True)
date_of_birth = models.DateField(null=True, blank=True)
guardian_name = models.CharField(max_length=255, null=True, blank=True)
phone = models.CharField(max_length=20, null=True, blank=True)
street = models.CharField(max_length=255, null=True, blank=True)
city = models.CharField(max_length=255, null=True, blank=True)
province = models.CharField(max_length=255, null=True, blank=True)
country = models.CharField(max_length=255, null=True, blank=True)
post_code = models.CharField(max_length=20, null=True, blank=True)
self_identification = models.CharField(max_length=255, null=True, blank=True)
gender = models.CharField(max_length=255, null=True, blank=True)
involvement = models.CharField(max_length=255, null=True, blank=True)
waiver = models.DateTimeField(null=True, blank=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = CustomMemberManager()
USERNAME_FIELD = 'email'
# REQUIRED_FIELDS = []
def get_full_name(self):
# The user is identified by their email address
if self.first_name and self.last_name:
return '{0} {1}'.format(self.first_name, self.last_name)
else:
return self.email
def get_short_name(self):
# The user is identified by their email address
return self.email
def __str__(self): # __unicode__ on Python 2
return self.email
@property
def is_staff(self):
# Simplest possible answer: All admins are staff
return self.is_admin

3
bikeshop_project/registration/tests.py

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

3
bikeshop_project/registration/views.py

@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.

11
package.json

@ -0,0 +1,11 @@
{
"name": "bikeshop",
"version": "0.0.1",
"description": "Maybe this isn't such a quick start, but it's the best I have right now. After the following steps are completed, you will have a working development version of the Trailer-Safeguard Django application connectable on [tsg-dev.local:8000/](http://tsg-dev.local:8000/).",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

14
provision/group_vars/all

@ -0,0 +1,14 @@
sudo: yes
# Application settings
app_name: bikeshop
app_user: "{{ app_name }}"
webapps_dir: /srv
settings_module: bikeshop.settings.{{ group_names[0] }}
app_dir: "{{ webapps_dir }}/{{ app_name }}"
venv: /opt/venv/{{ app_name }}-{{ group_names[0] }}
db_name: "{{ app_name }}_development"
db_user: "{{ app_name }}"
db_user_password: "{{ secret_db_user_password }}"
secret_db_user_password: password

11
provision/group_vars/production/non-secrets.yml

@ -0,0 +1,11 @@
postgresql_postgis: yes
app_dir: "{{ webapps_dir }}/{{ app_name }}"
db_name: "{{ app_name }}_production"
db_user: "{{ app_name }}"
db_user_password: "{{ secret_db_user_password }}"
django_key: "{{ secret_django_key }}"
app_domain_name: shop.bcbc.bike
app_port: 9999

10
provision/group_vars/production/secrets.yml

@ -0,0 +1,10 @@
$ANSIBLE_VAULT;1.1;AES256
32363235643965636135663037643239343762353631383934636533373537666561373063353261
6363393337636562653565303362366437313038633765330a396239336337356130353932656563
64623464623637323736376665343539353634326636333134363961653431303065373337616238
6633346461346266620a383536383331663262373736353230643736356134323136363230316136
61353131326165346564626237306630323962366239653837323463653639616363303562396662
32626165613563313130376438656561656664663231303839303935376335396533646534326661
38306561303432326236346365353034663736376335616434633332313735383236396431636532
36643163333762613065373861333265326363613365623330323135363739663931666466373961
6362

10
provision/group_vars/staging/non-secrets.yml

@ -0,0 +1,10 @@
postgresql_postgis: yes
db_name: "{{ app_name }}_staging"
db_user: "{{ app_name }}"
db_user_password: "{{ secret_db_user_password }}"
django_key: "{{ secret_django_key }}"
app_domain_name: 9mile.local
app_port: 9998

2
provision/group_vars/staging/secrets.yml

@ -0,0 +1,2 @@
secret_db_user_password: password
secret_django_key: somekey

5
provision/inventories/production

@ -0,0 +1,5 @@
[production]
1.1.1.1 ansible_ssh_private_key_file=~/.ssh/id_rsa
[servers:children]
production

3
provision/roles/app/tasks/main.yml

@ -0,0 +1,3 @@
- include: prepare.yml
- include: virtualenv.yml

5
provision/roles/app/tasks/prepare.yml

@ -0,0 +1,5 @@
---
- name: create webapps log directory
action: file dest={{ webapps_dir }}/{{ app_name }}/log state=directory
- name: create webapps directory
action: file dest={{ webapps_dir }} state=directory

15
provision/roles/app/tasks/virtualenv.yml

@ -0,0 +1,15 @@
---
- name: install virtualenv
action: pip executable=pip3 name=virtualenv state=present
- name: copy requirements
action: copy src=../requirements dest=/tmp
- name: create virtual environment
action: file dest={{ venv }} state=directory
- name: install requirements
action: pip executable=pip3 virtualenv={{ venv }} virtualenv_python=python3 requirements=/tmp/requirements/{{ group_names[0] }}.txt extra_args='--upgrade --force-reinstall'
register: requirements
tags:
- reqs

2
provision/roles/app/templates/sparse-checkout

@ -0,0 +1,2 @@
ninemilelegacy_project/core
ninemilelegacy_project/ninemilelegacy

22
provision/roles/common/tasks/main.yml

@ -0,0 +1,22 @@
---
- name: install packages needed to for building modules
action: apt update_cache=no pkg={{ item }} state=installed
with_items:
- build-essential
- autoconf
- git-core
- name: install nginx webserver
action: apt update_cache=no pkg=nginx state=installed
- name: install supervisord
action: apt update_cache=no pkg=supervisor state=installed
- name: install postfix
action: apt update_cache=no pkg=postfix state=installed
- name: install redis
action: apt name=redis-server update_cache=yes state=latest
- name: create app user
action: user createhome=no name={{ app_name }} state=present

18
provision/roles/database/tasks/main.yml

@ -0,0 +1,18 @@
---
- name: create a postgresql database
sudo: yes
sudo_user: postgres
action: postgresql_db name={{ db_name }} template=template0 state=present
- name: add a user to postgresql database
sudo: yes
sudo_user: postgres
action: postgresql_user db={{ db_name }} name={{ db_user }} password={{ db_user_password }} priv=ALL
- name: ensure database backkup directory is present
sudo: yes
action: file path=/var/backups/{{ db_name }} state=directory owner=postgres
- name: add a cron job to backup database every 1hr
sudo: yes
action: cron name='database backup' special_time=hourly user=postgres job='/usr/bin/pg_dump -Ft {{ db_name }} > /var/backups/{{ db_name }}/$(date +"\%Y\%m\%d\%H\%M\%S").tar'

36
provision/roles/deploy-code/tasks/main.yml

@ -0,0 +1,36 @@
---
- name: upload code
action: synchronize src=../bikeshop_project/ dest={{ app_dir }}
notify: restart supervisor
tags:
- deploy
- name: user owns directory
action: file path={{ app_dir }} owner={{ app_name }} state=directory recurse=yes
tags:
- deploy
- name: migrate database
action: django_manage command=migrate app_path={{ app_dir }} virtualenv={{ venv }} settings={{ settings_module }}
environment:
DJANGO_DB_PASSWORD: "{{ db_user_password }}"
DJANGO_SECRET_KEY: "{{ django_key }}"
tags:
- deploy
- name: collect static
action: django_manage command=collectstatic app_path={{ app_dir }} virtualenv={{ venv }} settings={{ settings_module }}
environment:
DJANGO_DB_PASSWORD: "{{ db_user_password }}"
DJANGO_SECRET_KEY: "{{ django_key }}"
tags:
- deploy
- name: load initial data in to database
action: django_manage command=loaddata fixtures=authentication/fixtures/initial_data.json app_path={{ app_dir }} virtualenv={{ venv }} settings={{ settings_module }}
environment:
DJANGO_DB_PASSWORD: "{{ db_user_password }}"
DJANGO_SECRET_KEY: "{{ django_key }}"
tags:
- deploy

14
provision/roles/django/tasks/main.yml

@ -0,0 +1,14 @@
- name: migrate app
action: django_manage command=migrate app_path={{ app_dir }} settings={{ settings_module }} virtualenv={{ venv }}
ignore_errors: yes
environment:
SECRET_KEY: "{{ django_key }}"
DB_PASSWORD: "{{ db_user_password }}"
- name: collect static
action: django_manage command="collectstatic --noinput" app_path={{ app_dir }} settings={{ settings_module }} virtualenv={{ venv }}
ignore_errors: yes
environment:
SECRET_KEY: "{{ django_key }}"
DB_PASSWORD: "{{ db_user_password }}"

3
provision/roles/handlers/main.yml

@ -0,0 +1,3 @@
---
- name: restart supervisor
service: name=supervisor state=restarted

2
provision/roles/nginx/handlers/main.yml

@ -0,0 +1,2 @@
- name: restart nginx
service: name=nginx state=restarted

12
provision/roles/nginx/tasks/main.yml

@ -0,0 +1,12 @@
---
- name: Configure nginx to run proxypass {{ app_name }}
action: template src={{ group_names[0] }}/nginx-site.conf dest=/etc/nginx/sites-available/{{ app_domain_name }}
notify: restart nginx
tags:
- nginx
- name: Enable {{ app_name }} nginx config
action: file src=/etc/nginx/sites-available/{{ app_domain_name }} dest=/etc/nginx/sites-enabled/{{ app_domain_name }} state=link
notify: restart nginx
tags:
- nginx

61
provision/roles/nginx/templates/production/nginx-site.conf

@ -0,0 +1,61 @@
server {
listen 80;
server_name www.{{ app_domain_name }};
# $scheme will get the http protocol
# and 301 is best practice for tablet, phone, desktop and seo
return 301 https://{{ app_domain_name }}$request_uri;
}
server {
listen 80;
server_name {{ app_domain_name }};
# $scheme will get the http protocol
# and 301 is best practice for tablet, phone, desktop and seo
return 301 https://{{ app_domain_name }}$request_uri;
}
server {
listen 443 ssl;
server_name {{ app_domain_name }};
ssl_certificate /etc/letsencrypt/live/{{ app_domain_name }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ app_domain_name }}/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root {{ app_dir }}/{{ app_name }};
}
location /media/ {
root {{ app_dir }}/{{ app_name }};
}
location / {
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 10;
proxy_read_timeout 10;
proxy_pass http://localhost:{{ app_port }}/;
}
}
server {
listen 4051;
server_name events.{{ app_domain_name }};
location /incoming/spikeEvent.php {
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 10;
proxy_read_timeout 10;
proxy_pass http://localhost:{{ app_port }}/incoming/;
}
}

31
provision/roles/nginx/templates/staging/nginx-site.conf

@ -0,0 +1,31 @@
server {
listen 80;
server_name www.{{ app_domain_name }};
# $scheme will get the http protocol
# and 301 is best practice for tablet, phone, desktop and seo
return 301 $scheme://{{ app_domain_name }}$request_uri;
}
server {
listen 80;
server_name {{ app_domain_name }};
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root {{ app_dir }};
}
location /media/ {
root {{ app_dir }};
}
location / {
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 10;
proxy_read_timeout 10;
proxy_pass http://localhost:{{ app_port }}/;
}
}

14
provision/roles/python/tasks/main.yml

@ -0,0 +1,14 @@
---
- name: install common packages needed for Python application development with PostgreSQL
action: apt update_cache=yes pkg={{ item }} state=installed
with_items:
- python3-dev
- python3-psycopg2
- python3-setuptools
- python3-pip
- libpq-dev
- libxml2-dev
- libxslt1-dev
#- name: install superlance (supervisor plugins)
# action: pip3 name=superlance

3
provision/roles/supervisor/handlers/main.yml

@ -0,0 +1,3 @@
---
- name: start supervisor
service: name=supervisor state=started

12
provision/roles/supervisor/tasks/main.yml

@ -0,0 +1,12 @@
---
- name: Configure supvervisor to run {{ app_name }}
action: template src={{ group_names[0] }}/supervisor-program.conf dest=/etc/supervisor/conf.d/{{ app_name }}.conf
tags:
- supervisor
- deploy
- name: Load and re-read group configs
action: supervisorctl name='{{ app_name }}:' state=present config=/etc/supervisor/supervisord.conf
tags:
- supvervisor
- deploy

4
provision/roles/supervisor/tasks/staging/main.yml

@ -0,0 +1,4 @@
---
- name: Configure supvervisor to run {{ app_name }}
action: template src=staging/supervisor-program.conf dest=/etc/supervisor/conf.d/{{ app_name }}.conf
notify: restart supervisor

45
provision/roles/supervisor/templates/production/supervisor-program.conf

@ -0,0 +1,45 @@
[group:{{ app_name }}]
programs=django,celerybeat,celeryworker
[program:django]
command={{ venv }}/bin/gunicorn -b 127.0.0.1:{{ app_port }} {{ app_name }}.wsgi:application
directory={{ app_dir }}
environment=DJANGO_DB_PASSWORD="{{ db_user_password }}",DJANGO_SECRET_KEY="{{ django_key }}",DJANGO_SETTINGS_MODULE="{{ settings_module }}"
autostart=true
autorestart=true
redirect_stderr=true
user={{ app_name }}
[program:celerybeat]
command={{ venv }}/bin/celery -A {{ app_name }} beat
environment=DJANGO_DB_PASSWORD="{{ db_user_password }}",DJANGO_SECRET_KEY="{{ django_key }}",DJANGO_SETTINGS_MODULE="{{ settings_module }}"
directory={{ app_dir }}
autostart=true
autorestart=true
redirect_stderr=true
user={{ app_name }}
[program:celeryworker]
command={{ venv }}/bin/celery -A {{ app_name }} worker
environment=DJANGO_DB_PASSWORD="{{ db_user_password }}",DJANGO_SECRET_KEY="{{ django_key }}",DJANGO_SETTINGS_MODULE="{{ settings_module }}",PYTHON_PATH={{ app_dir }}
directory={{ app_dir }}
autostart=true
autorestart=true
stdout_logfile=/var/log/celeryd/{{ app_name }}.log
stderr_logfile=/var/log/celeryd/{{ app_name }}.log
user={{ app_name }}
numprocs=1
startsecs=10
; Need to wait for currently executing tasks to finish at shutdown.
; Increase this if you have very long running tasks.
stopwaitsecs = 600
; When resorting to send SIGKILL to the program to terminate it
; send SIGKILL to its whole process group instead,
; taking care of its children as well.
killasgroup=true
; Set Celery priority higher than default (999)
; so, if rabbitmq is supervised, it will start first.
priority=1000

10
provision/roles/supervisor/templates/staging/supervisor-program.conf

@ -0,0 +1,10 @@
[program:{{ app_name }}]
command={{ venv }}/bin/gunicorn -b 127.0.0.1:{{ app_port }} {{ app_name }}.wsgi:application
directory={{ app_dir }}
environment=DB_PASSWORD="{{ db_user_password }}",DJANGO_SECRET_KEY="{{ django_key }}",DJANGO_SETTINGS_MODULE="{{settings_module}}"
autorestart=true
redirect_stderr=true
[eventlistener:memmon]
command=memmon -p {{ app_name }}=50MB -m vagrant@{{ app_domain_name}}
events=TICK_60

4
provision/roles/tasks/main.yml

@ -0,0 +1,4 @@
---
- name: Configure supvervisor to run {{ app_name }}
action: template src={{ group_names[0] }}/supervisor-program.conf dest=/etc/supervisor/conf.d/{{ app_name }}.conf
notify: restart supervisor

4
provision/roles/tasks/staging/main.yml

@ -0,0 +1,4 @@
---
- name: Configure supvervisor to run {{ app_name }}
action: template src=staging/supervisor-program.conf dest=/etc/supervisor/conf.d/{{ app_name }}.conf
notify: restart supervisor

11
provision/roles/templates/production/supervisor-program.conf

@ -0,0 +1,11 @@
[program:{{ app_name }}]
command={{ venv }}/bin/gunicorn -b 127.0.0.1:{{ app_port }} boxoffice.wsgi:application
directory={{ app_dir }}
environment=DB_PASSWORD="{{ db_user_password }}",OTB_SECRET_KEY="{{ django_key }}"
autostart=true
autorestart=true
redirect_stderr=true
[eventlistener:memmon]
command=memmon -p {{ app_name }}=50MB -m root
events=TICK_60

10
provision/roles/templates/staging/supervisor-program.conf

@ -0,0 +1,10 @@
[program:{{ app_name }}]
command={{ venv }}/bin/gunicorn -b 127.0.0.1:{{ app_port }} boxoffice.wsgi:application
directory={{ app_dir }}
environment=DB_PASSWORD="{{ db_user_password }}",OTB_SECRET_KEY="{{ django_key }}",DJANGO_SETTINGS_MODULE="boxoffice.settings.staging"
autorestart=true
redirect_stderr=true
[eventlistener:memmon]
command=memmon -p {{ app_name }}=50MB -m vagrant@ontheboards.local
events=TICK_60

1
provision/roles/zenoamaro.postgresql/.gitignore

@ -0,0 +1 @@
/.vagrant/

28
provision/roles/zenoamaro.postgresql/.travis.yml

@ -0,0 +1,28 @@
---
# Configuration directives for Travis CI
# --------------------------------------
# See the Travis documentation for help on writing this file.
# [Travis CI] http://travis-ci.org
# [configuration] http://about.travis-ci.org/docs/user/build-configuration/
language: python # Needed to run ansible
python:
- "2.7"
install:
- pip install ansible
script:
# Syntax check every ansible playbook in root
# Don't check main, though, as vars_prompt still
# trigger during syntax checks, and travis fails
- find . -maxdepth 1 -type f -name '*.yml' -not -name '.*' -not -name 'main.yml' | xargs -t -n1 ansible-playbook --syntax-check -i inventory
notifications:
email:
- zenoamaro@gmail.com

21
provision/roles/zenoamaro.postgresql/LICENSE.md

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015, zenoamaro <zenoamaro@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

117
provision/roles/zenoamaro.postgresql/README.md

@ -0,0 +1,117 @@
PostgreSQL role for Ansible
===========================
A role for deploying and configuring [PostgreSQL](http://www.postgresql.org/) and extensions on unix hosts using [Ansible](http://www.ansibleworks.com/).
It can additionally be used as a playbook for quickly provisioning hosts.
Vagrant machines are provided to produce a boxed install of PostgreSQL or a VM for integration testing.
Supports
--------
Supported PostgreSQL versions:
- PostgreSQL 9.4
- PostgreSQL 9.3
Supported targets:
- Ubuntu 14.04 LTS "Trusty Tahr"
- Ubuntu 12.04 LTS "Precise Pangolin"
- Debian (untested)
- RedHat (untested)
Installation methods:
- Binary packages from the official repositories at [postgresql.org](http://www.postgresql.org/download/)
Available extensions (under a switch):
- Development headers - `postgresql_dev_headers`
- Contrib modules - `postgresql_contrib`
- [PostGIS](http://postgis.net/) - `postgresql_postgis`
Usage
-----
Clone this repo into your roles directory:
$ git clone https://github.com/zenoamaro/ansible-postgresql.git roles/postgresql
And add it to your play's roles:
- hosts: ...
roles:
- postgresql
- ...
This roles comes preloaded with almost every available default. You can override each one in your hosts/group vars, in your inventory, or in your play. See the annotated defaults in `defaults/main.yml` for help in configuration. All provided variables start with `postgresql_`.
You can also use the role as a playbook. You will be asked which hosts to provision, and you can further configure the play by using `--extra-vars`.
$ ansible-playbook -i inventory --extra-vars='{...}' main.yml
To provision a standalone PostgreSQL box, start the `boxed` VM, which is a Ubuntu 12.04 box:
$ vagrant up boxed
You will find PostgreSQL listening on the VM's `5432` port on address `192.168.33.20` in the private network. You can then connect to it as any user. Please note that this is highly insecure, so if you're going to publish this VM you'll want to provide actual authentication.
Run the tests by provisioning the appropriate VM:
$ vagrant up test-ubuntu-trusty
At the moment, the following test boxes are available:
- `test-ubuntu-precise`
- `test-ubuntu-trusty`
Still to do
-----------
- Add repositories, tasks and test VMs for other distros
- Allow installation from sources if requested
- Add support for different PostgreSQL versions (9.4+)
- Add support for PostgreSQL clusters
- Add support for [PgBouncer](http://wiki.postgresql.org/wiki/PgBouncer)
- Try to make the boxed VM more secure by default
- Add links to the relevant documentation in configuration files
- Provide a library of custom modules
Changelog
---------
### 0.1.2
- Installing less dependencies, and later in the process.
### 0.1.1
- The package list is not being updated in playbooks anymore.
- Added more test machines.
### 0.1
Initial version.
License
-------
The MIT License (MIT)
Copyright (c) 2015, zenoamaro <zenoamaro@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

62
provision/roles/zenoamaro.postgresql/Vagrantfile

@ -0,0 +1,62 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure '2' do |config|
# Standalone box
# --------------
# Provision this machine to obtain a standalone box
# listening on the default ports.
config.vm.define 'boxed' do |box|
box.vm.box = "ubuntu/trusty64"
# Configure the network topology to your needs
config.vm.network :private_network, ip: "192.168.33.10"
# config.vm.network :public_network
config.vm.provision :ansible do |ansible|
ansible.playbook = './boxed.yml'
ansible.inventory_path = './inventory'
end
# Forward this postgres to a port on the host
config.vm.network :forwarded_port, guest: 5432, host: 15432
# TODO: What about also forwarding the data storage?
end
# Test machines
# -------------
# These test machines will configure the installation with all
# its extensions enabled, in order to test the validity
# of the role.
# Ubuntu machines are available:
# - "test-ubuntu-precise"
# - "test-ubuntu-trusty"
def apply_test_ansible_defaults(ansible)
ansible.playbook = './test.yml'
ansible.inventory_path = './inventory'
end
config.vm.define 'test-ubuntu-trusty', autostart:false do |box|
box.vm.box = "ubuntu/trusty64"
config.vm.network :private_network, ip: "192.168.33.21"
config.vm.provision :ansible do |ansible|
apply_test_ansible_defaults ansible
ansible.extra_vars = {}
end
end
config.vm.define 'test-ubuntu-precise', autostart:false do |box|
box.vm.box = "ubuntu/precise64"
config.vm.network :private_network, ip: "192.168.33.20"
config.vm.provision :ansible do |ansible|
apply_test_ansible_defaults ansible
ansible.extra_vars = {}
end
end
end

26
provision/roles/zenoamaro.postgresql/boxed.yml

@ -0,0 +1,26 @@
---
# Boxed installation playbook
# ---------------------------
# A Simple, straight playbook for producing
# a boxed installation in a vagrant VM.
- name: 'PostgreSQL boxed installation'
hosts: vagrant
vars:
postgresql_listen_addresses:
- '*'
postgresql_authentication:
- type: host
user: all
database: all
address: '0.0.0.0/0'
method: trust
roles:
- '.' # This role itself

606
provision/roles/zenoamaro.postgresql/defaults/main.yml

@ -0,0 +1,606 @@
---
postgresql_version: 9.4
# This will be the main admin user, which is only allowed to connect
# from localhost, mainly for provisioning, maintenance and scripts.
postgresql_admin_user: postgres
postgresql_admin_group: "{{postgresql_admin_user}}"
# TODO: This has been modeled but there's no real support for clusters yet
postgresql_cluster: main
# File locations
# --------------
# Store postgres' configuration files here
postgresql_conf_directory: "/etc/postgresql/{{postgresql_version}}/{{postgresql_cluster}}"
# Host-based authentication file
postgresql_hba_file: "{{postgresql_conf_directory}}/pg_hba.conf"
# Ident configuration file
postgresql_ident_file: "{{postgresql_conf_directory}}/pg_ident.conf"
# Use data in another directory
postgresql_data_directory: "/var/lib/postgresql/{{postgresql_version}}/{{postgresql_cluster}}"
# Directory to store runtime data such as PIDs
postgresql_runtime_directory: "/var/run/postgresql"
# If external_pid_file is not explicitly set, on extra PID file is written
postgresql_external_pid_file: "{{postgresql_runtime_directory}}/{{postgresql_version}}-{{postgresql_cluster}}.pid"
# Store postgresql's logs files here
postgresql_log_directory: "/var/log/postgresql"
# Connections and authentication
# ------------------------------
# Use 'localhost' for local addresses only. Use '*' alone to
# listen on every available address.
postgresql_listen_addresses:
- localhost
postgresql_port: 5432
# Authenticated connections that will be inserted in `pg_hba.conf`.
# These won't overwrite the default local idents, which are left
# untouched as they are useful and safe.
#
# Specify connections as a list of hashes having this schema:
# - type: local
# user: postgres
# method: peer
# database: 'all' # defaults to 'samerole', can also be a list
# address: '192.168.0.0/24' # optional
# options: # optional
# key: value
#
# The first field is the connection type: "local" is a Unix-domain
# socket, "host" is either a plain or SSL-encrypted TCP/IP socket,
# "hostssl" is an SSL-encrypted TCP/IP socket, and "hostnossl" is a
# plain TCP/IP socket.
#
# DATABASE can be "all", "sameuser", "samerole", "replication", a
# database name, or a comma-separated list thereof. The "all"
# keyword does not match "replication". Access to replication
# must be enabled in a separate record (see example below).
#
# USER can be "all", a user name, a group name prefixed with "+", or a
# comma-separated list thereof. In both the DATABASE and USER fields
# you can also write a file name prefixed with "@" to include names
# from a separate file.
#
# ADDRESS specifies the set of hosts the record matches. It can be a
# host name, or it is made up of an IP address and a CIDR mask that is
# an integer (between 0 and 32 (IPv4) or 128 (IPv6) inclusive) that
# specifies the number of significant bits in the mask. A host name
# that starts with a dot (.) matches a suffix of the actual host name.
# Alternatively, you can write an IP address and netmask in separate
# columns to specify the set of hosts. Instead of a CIDR-address, you
# can write "samehost" to match any of the server's own IP addresses,
# or "samenet" to match any address in any subnet that the server is
# directly connected to.
#
# METHOD can be "trust", "reject", "md5", "password", "gss", "sspi",
# "krb5", "ident", "peer", "pam", "ldap", "radius" or "cert". Note that
# "password" sends passwords in clear text; "md5" is preferred since
# it sends encrypted passwords.
#
# Database and user names containing spaces, commas, quotes and other
# special characters must be quoted. Quoting one of the keywords
# "all", "sameuser", "samerole" or "replication" makes the name lose
# its special character, and just match a database or username with
# that name.
postgresql_authentication: []
# Authenticated connections that will be inserted in `pg_hba.conf`.
# These won't overwrite the default local idents, which are left
# untouched as they are useful and safe.
# Specify connections as a list of hashes having this schema:
# - name: map_a
# user: system_user
# pg_user: postgresql_user
postgresql_user_map: []
# A dict whose `key: value`s will be provided as environment
# variables for the postmaster.
postgresql_env: {}
# Note: Increasing max_connections costs ~400 bytes of shared memory per
# connection slot, plus lock space (see max_locks_per_transaction).
postgresql_max_connections: 1024
postgresql_superuser_reserved_connections: 3
postgresql_unix_socket_directories: # comma-separated list of directories
- /var/run/postgresql
postgresql_unix_socket_group: ''
postgresql_unix_socket_permissions: '0777' # begin with 0 to use octal notation
# Automatic pg_ctl configuration. Specify a list of options containing
# cluster specific options to be passed to pg_ctl(1).
postgresql_pg_ctl_options: []
postgresql_bonjour: off # advertise server via Bonjour
postgresql_bonjour_name: '' # defaults to the computer name
# Security and Authentication
# ---------------------------
postgresql_authentication_timeout: 60s
postgresql_ssl: off
postgresql_ssl_ciphers:
- 'DEFAULT'
- '!LOW'
- '!EXP'
- '!MD5'
- '@STRENGTH'
postgresql_ssl_renegotiation_limit: 512MB # amount of data between renegotiations
postgresql_ssl_cert_file: /etc/ssl/certs/ssl-cert-snakeoil.pem
postgresql_ssl_key_file: /etc/ssl/private/ssl-cert-snakeoil.key
postgresql_ssl_ca_file: ''
postgresql_ssl_crl_file: ''
postgresql_password_encryption: on
postgresql_db_user_namespace: off
# Kerberos and GSSAPI
postgresql_krb_server_keyfile: ''
postgresql_krb_caseins_users: off
# TCP Keepalives, 0 selects the system default
postgresql_tcp_keepalives_idle: 0
postgresql_tcp_keepalives_interval: 0
postgresql_tcp_keepalives_count: 0
# Memory
# ------
postgresql_shared_buffers: 128MB # min 128kB
postgresql_temp_buffers: 8MB # min 800kB
postgresql_work_mem: 1MB # min 64kB
postgresql_maintenance_work_mem: 16MB # min 1MB
postgresql_max_stack_depth: 2MB # min 100kB
# Note: Increasing max_prepared_transactions costs ~600 bytes of shared memory
# per transaction slot, plus lock space (see max_locks_per_transaction).
# It is not advisable to set max_prepared_transactions nonzero unless you
# actively intend to use prepared transactions.
postgresql_max_prepared_transactions: 0 # zero disables the feature
# Disk
# ----
# limits per-session temp file space in kB, or -1 for off limit
postgresql_temp_file_limit: -1
# Kernel Resource Usage
# ---------------------
postgresql_max_files_per_process: 1000 # min 25
postgresql_shared_preload_libraries: []
# Lock Management
# ---------------
postgresql_deadlock_timeout: 1s
postgresql_max_locks_per_transaction: 64 # min 10
# Note: Each lock table slot uses ~270 bytes of shared memory, and there are
# max_locks_per_transaction * (max_connections + max_prepared_transactions)
# lock table slots.
postgresql_max_pred_locks_per_transaction: 64 # min 10
# Write Ahead Log
# ---------------
postgresql_wal_level: minimal # minimal, archive, or hot_standby
postgresql_fsync: on # turns forced synchronization on or off
# Synchronization level:
# - off
# - local
# - remote_write
# - on
postgresql_synchronous_commit: on
# The default is the first option supported by the operating system:
# - open_datasync
# - fdatasync (default on Linux)
# - fsync
# - fsync_writethrough
# - open_sync
postgresql_wal_sync_method: fsync
# recover from partial page writes
postgresql_full_page_writes: on
postgresql_wal_buffers: -1 # min 32kB, -1 sets based on shared_buffers
postgresql_wal_writer_delay: 200ms # 1-10000 milliseconds
postgresql_commit_delay: 0 # range 0-100000, in microseconds
postgresql_commit_siblings: 5 # range 1-1000
postgresql_checkpoint_segments: 3 # in logfile segments, min 1, 16MB each
postgresql_checkpoint_timeout: 5min # range 30s-1h
postgresql_checkpoint_completion_target: 0.5 # checkpoint target duration, 0.0 - 1.0
postgresql_checkpoint_warning: 30s # 0 disables
# allows archiving to be done
postgresql_archive_mode: off
# Command to use to archive a logfile segment.
# Placeholders: %p = path of file to archive
# %f = file name only
# e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
postgresql_archive_command: ''
# force a logfile segment switch after this
postgresql_archive_timeout: 0
# Replication
# -----------
# Set these on the master and on any standby that will send replication data.
# max number of walsender processes
postgresql_max_wal_senders: 0
postgresql_wal_keep_segments: 0 # in logfile segments, 16MB each; 0 disables
postgresql_wal_sender_timeout: 60s # in milliseconds; 0 disables
# Replication (masters)
# ---------------------
# These settings are ignored on a standby server.
# Standby servers that provide sync rep.
# Comma-separated list of application_name from standby(s)
postgresql_synchronous_standby_names: [] # '*' means 'all'
# number of xacts by which cleanup is delayed
postgresql_vacuum_defer_cleanup_age: 0
# "on" allows queries during recovery
postgresql_hot_standby: off
# max delay before canceling queries when reading WAL from archive
postgresql_max_standby_archive_delay: 30s # -1 allows indefinite delay
# max delay before canceling queries when reading streaming WAL;
postgresql_max_standby_streaming_delay: 30s # -1 allows indefinite delay
# send replies at least this often
postgresql_wal_receiver_status_interval: 10s # 0 disables
# send info from standby to prevent query conflicts
postgresql_hot_standby_feedback: off
#time that receiver waits for communication from master in milliseconds
postgresql_wal_receiver_timeout: 60s
# Error Reporting And Logging
# ---------------------------
# Valid values are combinations of stderr, csvlog, syslog, and eventlog.
# depending on platform. Csvlog requires logging_collector to be on.
postgresql_log_destination: stderr
# Enable capturing of stderr and csvlog into log files.
# Required to be on for csvlogs.
postgresql_logging_collector: on
# These are only used if logging_collector is on:
# Log file name pattern, can include strftime() escapes
postgresql_log_filename: postgresql-%Y-%m-%d_%H%M%S.log
postgresql_log_file_mode: '0600' # begin with 0 to use octal notation
# If on, an existing log file with the same name as the new log file will be
# truncated rather than appended to. But such truncation only occurs on
# time-driven rotation, not on restarts or size-driven rotation. Default is
# off, meaning append to existing files in all cases.
postgresql_log_truncate_on_rotation: off
# Automatic rotation of logfiles will happen after that time.
postgresql_log_rotation_age: 1d
# Automatic rotation of logfiles will happen after that much log output.
postgresql_log_rotation_size: 10MB
# These are relevant when logging to syslog:
postgresql_syslog_facility: LOCAL0
postgresql_syslog_ident: postgres
# This is only relevant when logging to eventlog (win32):
postgresql_event_source: PostgreSQL
# Values in order of decreasing detail:
# - debug5
# - debug4
# - debug3
# - debug2
# - debug1
# - log
# - notice
# - warning
# - error
postgresql_client_min_messages: notice
# Values in order of decreasing detail:
# - debug5
# - debug4
# - debug3
# - debug2
# - debug1
# - info
# - notice
# - warning
# - error
# - log
# - fatal
# - panic
postgresql_log_min_messages: warning
# Values in order of decreasing detail:
# - debug5
# - debug4
# - debug3
# - debug2
# - debug1
# - info
# - notice
# - warning
# - error
# - log
# - fatal
# - panic (effectively off)
postgresql_log_min_error_statement: error
# -1 is disabled, 0 logs all statements and their durations, > 0 logs only
# statements running at least this number of milliseconds
postgresql_log_min_duration_statement: -1
postgresql_debug_print_parse: off
postgresql_debug_print_rewritten: off
postgresql_debug_print_plan: off
postgresql_debug_pretty_print: on
postgresql_log_checkpoints: off
postgresql_log_connections: off
postgresql_log_disconnections: off
postgresql_log_duration: off
postgresql_log_error_verbosity: default # terse, default, or verbose messages
postgresql_log_hostname: off
# Special values:
# %a = application name
# %u = user name
# %d = database name
# %r = remote host and port
# %h = remote host
# %p = process ID
# %t = timestamp without milliseconds
# %m = timestamp with milliseconds
# %i = command tag
# %e = SQL state
# %c = session ID
# %l = session line number
# %s = sessioan start timestamp
# %v = virtual transaction ID
# %x = transaction ID (0 if none)
# %q = stop here in non-session
# processes
# %% = '%'
postgresql_log_line_prefix: '%t '
# log lock waits >= deadlock_timeout
postgresql_log_lock_waits: off
postgresql_log_statement: none # none, ddl, mod, all
# log temporary files equal or larger
postgresql_log_temp_files: -1
postgresql_log_timezone: UTC
# Runtime statistics
# ------------------
postgresql_track_activities: on
postgresql_track_counts: on
postgresql_track_io_timing: off
postgresql_track_functions: none # none, pl, all
postgresql_track_activity_query_size: 1024
postgresql_update_process_title: on
postgresql_stats_temp_directory: pg_stat_tmp
postgresql_log_parser_stats: off
postgresql_log_planner_stats: off
postgresql_log_executor_stats: off
postgresql_log_statement_stats: off
# Error Handling
# --------------
# Terminate session on any error?
postgresql_exit_on_error: off
# Reinitialize after backend crash?
postgresql_restart_after_crash: on
# Query Tuning (Planner)
# ----------------------
postgresql_enable_bitmapscan: on
postgresql_enable_hashagg: on
postgresql_enable_hashjoin: on
postgresql_enable_indexscan: on
postgresql_enable_indexonlyscan: on
postgresql_enable_material: on
postgresql_enable_mergejoin: on
postgresql_enable_nestloop: on
postgresql_enable_seqscan: on
postgresql_enable_sort: on
postgresql_enable_tidscan: on
postgresql_seq_page_cost: 1.0 # measured on an arbitrary scale
postgresql_random_page_cost: 4.0 # same scale as above
postgresql_cpu_tuple_cost: 0.01 # same scale as above
postgresql_cpu_index_tuple_cost: 0.005 # same scale as above
postgresql_cpu_operator_cost: 0.0025 # same scale as above
postgresql_effective_cache_size: 128MB
# Query Tuning (Genetic Query Optimizer)
# --------------------------------------
postgresql_geqo: on
postgresql_geqo_threshold: 12
postgresql_geqo_effort: 5 # range 1-10
postgresql_geqo_pool_size: 0 # selects default based on effort
postgresql_geqo_generations: 0 # selects default based on effort
postgresql_geqo_selection_bias: 2.0 # range 1.5-2.0
postgresql_geqo_seed: 0.0 # range 0.0-1.0
# Query Tuning (Other Planner Options)
# ------------------------------------
postgresql_default_statistics_target: 100 # range 1-10000
postgresql_constraint_exclusion: partition # on, off, or partition
postgresql_cursor_tuple_fraction: 0.1 # range 0.0-1.0
postgresql_from_collapse_limit: 8
postgresql_join_collapse_limit: 8 # 1 disables collapsing of explicit
# Cost-Based Vacuum Delay
# -----------------------
postgresql_vacuum_cost_delay: 0 # 0-100 milliseconds
postgresql_vacuum_cost_page_hit: 1 # 0-10000 credits
postgresql_vacuum_cost_page_miss: 10 # 0-10000 credits
postgresql_vacuum_cost_page_dirty: 20 # 0-10000 credits
postgresql_vacuum_cost_limit: 200 # 1-10000 credits
# Autovacuum Parameters
# ---------------------
# Enable autovacuum subprocess? 'on' requires track_counts to also be on.
postgresql_autovacuum: on
# -1 disables, 0 logs all actions and their durations, > 0 logs only
# actions running at least this number of milliseconds.
postgresql_log_autovacuum_min_duration: -1
# max number of autovacuum subprocesses
postgresql_autovacuum_max_workers: 3
# time between autovacuum runs
postgresql_autovacuum_naptime: 1min
# min number of row updates before vacuum
postgresql_autovacuum_vacuum_threshold: 50
# min number of row updates before analyze
postgresql_autovacuum_analyze_threshold: 50
# fraction of table size before vacuum
postgresql_autovacuum_vacuum_scale_factor: 0.2
# fraction of table size before analyze
postgresql_autovacuum_analyze_scale_factor: 0.1
# maximum XID age before forced vacuum
postgresql_autovacuum_freeze_max_age: 200000000
# default vacuum cost delay for autovacuum, in milliseconds
postgresql_autovacuum_vacuum_cost_delay: 20ms
# default vacuum cost limit for autovacuum,
postgresql_autovacuum_vacuum_cost_limit: -1
# Background Writer
# -----------------
postgresql_bgwriter_delay: 200ms # 10-10000ms between rounds
postgresql_bgwriter_lru_maxpages: 100 # 0-1000 max buffers written/round
postgresql_bgwriter_lru_multiplier: 2.0 # 0-10.0 multipler on buffers scanned/round
# Asynchronous Behavior
# ---------------------
postgresql_effective_io_concurrency: 1 # 1-1000; 0 disables prefetching
# Client Connection Defaults
# --------------------------
postgresql_search_path: # schema names
- '"$user"'
- public
postgresql_default_tablespace: '' # a tablespace name, '' uses the default
postgresql_temp_tablespaces: [] # a list of tablespace names
postgresql_check_function_bodies: on
postgresql_default_transaction_isolation: read committed
postgresql_default_transaction_read_only: off
postgresql_default_transaction_deferrable: off
postgresql_session_replication_role: origin
postgresql_statement_timeout: 0 # in milliseconds, 0 is disabled
postgresql_lock_timeout: 0 # in milliseconds, 0 is disabled
postgresql_vacuum_freeze_min_age: 50000000
postgresql_vacuum_freeze_table_age: 150000000
postgresql_bytea_output: hex # hex, escape
postgresql_xmlbinary: base64
postgresql_xmloption: content
# Select the set of available time zone abbreviations. Currently, there are:
# Default
# Australia
# India
# You can create your own file in `share/timezonesets/`.
postgresql_timezone_abbreviations: Default
postgresql_datestyle:
- iso
- mdy
postgresql_intervalstyle: postgres
postgresql_timezone: UTC
postgresql_extra_float_digits: 0 # min -15, max 3
postgresql_client_encoding: sql_ascii # 'sql_ascii' actually defaults to database encoding
# These settings are initialized by initdb, but they can be changed.
# locale for system error message
postgresql_lc_messages: en_US.UTF-8
# locale for monetary formatting
postgresql_lc_monetary: en_US.UTF-8
# locale for number formatting
postgresql_lc_numeric: en_US.UTF-8
# locale for time formatting
postgresql_lc_time: en_US.UTF-8
postgresql_default_text_search_config: pg_catalog.english
postgresql_dynamic_library_path: '$libdir'
postgresql_local_preload_libraries: []
# Version/platform Compatibility
# ------------------------------
postgresql_array_nulls: on
postgresql_backslash_quote: safe_encoding # on, off, or safe_encoding
postgresql_default_with_oids: off
postgresql_escape_string_warning: on
postgresql_lo_compat_privileges: off
postgresql_quote_all_identifiers: off
postgresql_sql_inheritance: on
postgresql_standard_conforming_strings: on
postgresql_synchronize_seqscans: on
postgresql_transform_null_equals: off
# Extensions
# ----------
# If enabled, this will install the contrib packages.
postgresql_contrib: no
# If enabled, will install the [PostGIS] extension
# from the repositories, at the indicated version.
# [PostGIS] http://postgis.net/
postgresql_postgis: no
postgresql_postgis_version: '2.1'
# If enabled, this will install the development headers.
postgresql_dev_headers: no

8
provision/roles/zenoamaro.postgresql/handlers/main.yml

@ -0,0 +1,8 @@
---
- name: restart postgresql
sudo: yes
service: name=postgresql state=restarted
- name: reload postgresql
sudo: yes
service: name=postgresql state=reloaded

19
provision/roles/zenoamaro.postgresql/inventory

@ -0,0 +1,19 @@
[boxed]
192.168.33.10 ansible_ssh_private_key_file=.vagrant/machines/boxed/virtualbox/private_key
[test-ubuntu-precise]
192.168.33.20 ansible_ssh_private_key_file=.vagrant/machines/test-ubuntu-precise/virtualbox/private_key
[test-ubuntu-trusty]
192.168.33.21 ansible_ssh_private_key_file=.vagrant/machines/test-ubuntu-trusty/virtualbox/private_key
[test:children]
test-ubuntu-precise
test-ubuntu-trusty
[vagrant:children]
test
boxed
[vagrant:vars]
ansible_ssh_user=vagrant

19
provision/roles/zenoamaro.postgresql/main.yml

@ -0,0 +1,19 @@
---
# Quick-provisioning playbook
# ---------------------------
# A Simple, straight playbook for quick remote installations.
# You will be asked which hosts to provision before-hand.
- name: 'PostgreSQL'
vars_prompt:
selected_hosts: Specify the hosts to provision
hosts: "{{selected_hosts}}"
roles:
- '.' # The current directory itself is the role

1
provision/roles/zenoamaro.postgresql/meta/.galaxy_install_info

@ -0,0 +1 @@
{install_date: 'Thu Feb 25 15:47:50 2016', version: v0.1.2}

21
provision/roles/zenoamaro.postgresql/meta/main.yml

@ -0,0 +1,21 @@
---
galaxy_info:
author: zenoamaro
description: A role for installing and configuring PostgreSQL
version: 0.1.2
license: MIT
min_ansible_version: 1.4
platforms:
- name: Debian
- name: Ubuntu
versions:
- precise
- trusty
categories:
- database
- database:sql
dependencies: []

55
provision/roles/zenoamaro.postgresql/tasks/configure.yml

@ -0,0 +1,55 @@
---
- name: Create the necessary directories
sudo: yes
file:
dest: "{{item}}"
state: directory
owner: "{{postgresql_admin_user}}"
group: "{{postgresql_admin_group}}"
with_items:
- "{{postgresql_conf_directory}}"
- "{{postgresql_data_directory}}"
- "{{postgresql_runtime_directory}}"
- "{{postgresql_log_directory}}"
tags:
- postgresql
- db
- conf
- name: Configure PostgreSQL
sudo: yes
template:
src: "{{item}}"
dest: "{{postgresql_conf_directory}}/{{item}}"
with_items:
- postgresql.conf
- pg_ctl.conf
- environment
notify: restart postgresql
tags:
- postgresql
- db
- conf
- name: Configure PostgreSQL (authentication)
sudo: yes
template:
src: pg_hba.conf
dest: "{{postgresql_hba_file}}"
notify: restart postgresql
tags:
- postgresql
- db
- conf
- name: Configure PostgreSQL (ident)
sudo: yes
template:
src: pg_ident.conf
dest: "{{postgresql_ident_file}}"
notify: restart postgresql
tags:
- postgresql
- db
- conf

49
provision/roles/zenoamaro.postgresql/tasks/extensions.yml

@ -0,0 +1,49 @@
---
# Development headers and libraries
# ---------------------------------
- name: Install development headers
when: postgresql_dev_headers == True
sudo: yes
apt:
name: libpq-dev
tags:
- postgresql
- db
- deps
- dev
# Contributed extensions
# ----------------------
- name: Install PostgreSQL contribs
when: postgresql_contrib
sudo: yes
apt:
name: "postgresql-contrib-{{postgresql_version}}"
notify: restart postgresql
tags:
- postgresql
- db
- deps
# PostGIS
# -------
- name: Add postgis extensions
when: postgresql_postgis
sudo: yes
apt:
name: "{{item}}"
with_items:
- "postgresql-{{postgresql_version}}-postgis-{{postgresql_postgis_version}}"
- libgeos-c1
notify: restart postgresql
tags:
- postgresql
- db
- deps

51
provision/roles/zenoamaro.postgresql/tasks/install.yml

@ -0,0 +1,51 @@
---
# Official PostgreSQL [repository] for debian-based distributions
# [repository]: http://www.postgresql.org/download/
- name: Adding APT repository key
when: ansible_os_family == 'Debian'
sudo: yes
apt_key:
id: ACCC4CF8
url: https://www.postgresql.org/media/keys/ACCC4CF8.asc
tags:
- postgresql
- db
- repo
- name: Add PostgreSQL official APT repository
when: ansible_os_family == 'Debian'
sudo: yes
apt_repository:
repo: "deb http://apt.postgresql.org/pub/repos/apt/ {{ansible_distribution_release}}-pgdg main"
tags:
- postgresql
- db
- repo
- name: Install PostgreSQL
when: ansible_os_family == 'Debian'
sudo: yes
apt:
name: "postgresql-{{postgresql_version}}"
state: present
update_cache: yes
cache_valid_time: 3600
tags:
- postgresql
- db
- deps
- name: Install dependencies for the Ansible module
when: ansible_os_family == 'Debian'
sudo: yes
apt:
name: "{{item}}"
state: latest
with_items:
- python-psycopg2
tags:
- postgresql
- db
- deps

5
provision/roles/zenoamaro.postgresql/tasks/main.yml

@ -0,0 +1,5 @@
---
- include: install.yml
- include: extensions.yml
- include: configure.yml

11
provision/roles/zenoamaro.postgresql/templates/environment

@ -0,0 +1,11 @@
# environment variables for postmaster process
# This file has the same syntax as postgresql.conf:
# VARIABLE = simple_value
# VARIABLE2 = 'any value!'
# I. e. you need to enclose any value which does not only consist of letters,
# numbers, and '-', '_', '.' in single quotes. Shell commands are not
# evaluated.
{% if postgresql_env %}{% for k,v in postgresql_env.items() %}
{{k}} = {{v}}
{% endfor %}{% endif %}

5
provision/roles/zenoamaro.postgresql/templates/pg_ctl.conf

@ -0,0 +1,5 @@
# Automatic pg_ctl configuration
# This configuration file contains cluster specific options to be passed to
# pg_ctl(1).
pg_ctl_options = '{{ postgresql_pg_ctl_options|join(' ')|replace('\'', '\\\'') }}'

112
provision/roles/zenoamaro.postgresql/templates/pg_hba.conf

@ -0,0 +1,112 @@
# PostgreSQL Client Authentication Configuration File
# ===================================================
#
# Refer to the "Client Authentication" section in the PostgreSQL
# documentation for a complete description of this file. A short
# synopsis follows.
#
# This file controls: which hosts are allowed to connect, how clients
# are authenticated, which PostgreSQL user names they can use, which
# databases they can access. Records take one of these forms:
#
# local DATABASE USER METHOD [OPTIONS]
# host DATABASE USER ADDRESS METHOD [OPTIONS]
# hostssl DATABASE USER ADDRESS METHOD [OPTIONS]
# hostnossl DATABASE USER ADDRESS METHOD [OPTIONS]
#
# (The uppercase items must be replaced by actual values.)
#
# The first field is the connection type: "local" is a Unix-domain
# socket, "host" is either a plain or SSL-encrypted TCP/IP socket,
# "hostssl" is an SSL-encrypted TCP/IP socket, and "hostnossl" is a
# plain TCP/IP socket.
#
# DATABASE can be "all", "sameuser", "samerole", "replication", a
# database name, or a comma-separated list thereof. The "all"
# keyword does not match "replication". Access to replication
# must be enabled in a separate record (see example below).
#
# USER can be "all", a user name, a group name prefixed with "+", or a
# comma-separated list thereof. In both the DATABASE and USER fields
# you can also write a file name prefixed with "@" to include names
# from a separate file.
#
# ADDRESS specifies the set of hosts the record matches. It can be a
# host name, or it is made up of an IP address and a CIDR mask that is
# an integer (between 0 and 32 (IPv4) or 128 (IPv6) inclusive) that
# specifies the number of significant bits in the mask. A host name
# that starts with a dot (.) matches a suffix of the actual host name.
# Alternatively, you can write an IP address and netmask in separate
# columns to specify the set of hosts. Instead of a CIDR-address, you
# can write "samehost" to match any of the server's own IP addresses,
# or "samenet" to match any address in any subnet that the server is
# directly connected to.
#
# METHOD can be "trust", "reject", "md5", "password", "gss", "sspi",
# "krb5", "ident", "peer", "pam", "ldap", "radius" or "cert". Note that
# "password" sends passwords in clear text; "md5" is preferred since
# it sends encrypted passwords.
#
# OPTIONS are a set of options for the authentication in the format
# NAME=VALUE. The available options depend on the different
# authentication methods -- refer to the "Client Authentication"
# section in the documentation for a list of which options are
# available for which authentication methods.
#
# Database and user names containing spaces, commas, quotes and other
# special characters must be quoted. Quoting one of the keywords
# "all", "sameuser", "samerole" or "replication" makes the name lose
# its special character, and just match a database or username with
# that name.
#
# This file is read on server startup and when the postmaster receives
# a SIGHUP signal. If you edit the file on a running system, you have
# to SIGHUP the postmaster for the changes to take effect. You can
# use "pg_ctl reload" to do that.
# Put your actual configuration here
# ----------------------------------
#
# If you want to allow non-local connections, you need to add more
# "host" records. In that case you will also need to make PostgreSQL
# listen on a non-local interface via the listen_addresses
# configuration parameter, or via the -i or -h command line switches.
# TYPE DATABASE USER ADDRESS METHOD
{% for auth in postgresql_authentication %}
{{auth.type}} {% if 'database' not in auth %}
samerole{% elif auth.database is string %}
{{auth.database}}{% elif auth.database is sequence %}
{{auth.database|join(',')}}{% endif %} {{auth.user}} {{auth.address|default('')}} {{auth.method}} {% if 'options' in auth %} {% for k,v in auth.options.items() %}
{{k}}={{v}} {% endfor %}{% endif %}
{% endfor %}
# DO NOT DISABLE!
# If you change this first entry you will need to make sure that the
# database superuser can access the database using some other method.
# Noninteractive access to all databases is required during automatic
# maintenance (custom daily cronjobs, replication, and similar tasks).
#
# Database administrative login by Unix domain socket
# TYPE DATABASE USER ADDRESS METHOD
local all {{postgresql_admin_user|default('postgres')}} peer
# "local" is for Unix domain socket connections only
local all all peer
# IPv4 local connections:
host all all 127.0.0.1/32 md5
# IPv6 local connections:
host all all ::1/128 md5
# Allow replication connections from localhost, by a user with the
# replication privilege.
#local replication postgres peer
#host replication postgres 127.0.0.1/32 md5
#host replication postgres ::1/128 md5

46
provision/roles/zenoamaro.postgresql/templates/pg_ident.conf

@ -0,0 +1,46 @@
# PostgreSQL User Name Maps
# =========================
#
# Refer to the PostgreSQL documentation, chapter "Client
# Authentication" for a complete description. A short synopsis
# follows.
#
# This file controls PostgreSQL user name mapping. It maps external
# user names to their corresponding PostgreSQL user names. Records
# are of the form:
#
# MAPNAME SYSTEM-USERNAME PG-USERNAME
#
# (The uppercase quantities must be replaced by actual values.)
#
# MAPNAME is the (otherwise freely chosen) map name that was used in
# pg_hba.conf. SYSTEM-USERNAME is the detected user name of the
# client. PG-USERNAME is the requested PostgreSQL user name. The
# existence of a record specifies that SYSTEM-USERNAME may connect as
# PG-USERNAME.
#
# If SYSTEM-USERNAME starts with a slash (/), it will be treated as a
# regular expression. Optionally this can contain a capture (a
# parenthesized subexpression). The substring matching the capture
# will be substituted for \1 (backslash-one) if present in
# PG-USERNAME.
#
# Multiple maps may be specified in this file and used by pg_hba.conf.
#
# No map names are defined in the default configuration. If all
# system user names and PostgreSQL user names are the same, you don't
# need anything in this file.
#
# This file is read on server startup and when the postmaster receives
# a SIGHUP signal. If you edit the file on a running system, you have
# to SIGHUP the postmaster for the changes to take effect. You can
# use "pg_ctl reload" to do that.
# Put your actual configuration here
# ----------------------------------
# MAPNAME SYSTEM-USERNAME PG-USERNAME
{% for mapping in postgresql_user_map %}
{{mapping.name}} {{mapping.user}} {{mapping.pg_user}}
{% endfor %}

530
provision/roles/zenoamaro.postgresql/templates/postgresql.conf

@ -0,0 +1,530 @@
# Memory units: kB = kilobytes Time units: ms = milliseconds
# MB = megabytes s = seconds
# GB = gigabytes min = minutes
# h = hours
# d = days
# File locations
# --------------
# The default values of these variables are driven from the -D command-line
# option or PGDATA environment variable, represented here as ConfigDir.
# use data in another directory (change requires restart)
data_directory = '{{postgresql_data_directory}}'
# host-based authentication file (change requires restart)
hba_file = '{{postgresql_hba_file}}'
# ident configuration file (change requires restart)
ident_file = '{{postgresql_ident_file}}'
# If external_pid_file is not explicitly set, no extra PID file is written.
# write an extra PID file (change requires restart)
external_pid_file = '{{postgresql_external_pid_file}}'
# Connections
# -----------
# What IP address(es) to listen on; comma-separated list of addresses.
listen_addresses = '{{postgresql_listen_addresses|join(', ')}}'
port = {{postgresql_port}}
# Note: Increasing max_connections costs ~400 bytes of shared memory per
# connection slot, plus lock space (see max_locks_per_transaction).
max_connections = {{postgresql_max_connections}}
superuser_reserved_connections = {{postgresql_superuser_reserved_connections}}
unix_socket_directories = '{{postgresql_unix_socket_directories|join(',')}}' # comma-separated list of directories
unix_socket_group = '{{postgresql_unix_socket_group}}'
unix_socket_permissions = {{postgresql_unix_socket_permissions}} # begin with 0 to use octal notation
bonjour = {{'on' if postgresql_bonjour else 'off'}} # advertise server via Bonjour
bonjour_name = '{{postgresql_bonjour_name}}' # defaults to the computer name
# Security and Authentication
# ---------------------------
authentication_timeout = {{postgresql_authentication_timeout}}
ssl = {{'on' if postgresql_ssl else 'off'}}
ssl_ciphers = '{{postgresql_ssl_ciphers|join(':')}}'
ssl_renegotiation_limit = {{postgresql_ssl_renegotiation_limit}}
ssl_cert_file = '{{postgresql_ssl_cert_file}}'
ssl_key_file = '{{postgresql_ssl_key_file}}'
ssl_ca_file = '{{postgresql_ssl_ca_file}}'
ssl_crl_file = '{{postgresql_ssl_crl_file}}'
password_encryption = {{'on' if postgresql_password_encryption else 'off'}}
db_user_namespace = {{'on' if postgresql_db_user_namespace else 'off'}}
# Kerberos and GSSAPI
krb_server_keyfile = '{{postgresql_krb_server_keyfile}}'
krb_caseins_users = {{'on' if postgresql_db_user_namespace else 'off'}}
# TCP Keepalives, 0 selects the system default
tcp_keepalives_idle = {{postgresql_tcp_keepalives_idle}}
tcp_keepalives_interval = {{postgresql_tcp_keepalives_interval}}
tcp_keepalives_count = {{postgresql_tcp_keepalives_count}}
# Memory
# ------
shared_buffers = {{postgresql_shared_buffers}}
temp_buffers = {{postgresql_temp_buffers}}
# Note: Increasing max_prepared_transactions costs ~600 bytes of shared memory
# per transaction slot, plus lock space (see max_locks_per_transaction).
# It is not advisable to set max_prepared_transactions nonzero unless you
# actively intend to use prepared transactions.
max_prepared_transactions = {{postgresql_max_prepared_transactions}} # 0 disables the feature
work_mem = {{postgresql_work_mem}} # min 64kB
maintenance_work_mem = {{postgresql_maintenance_work_mem}} # min 1MB
max_stack_depth = {{postgresql_max_stack_depth}} # min 100kB
# Disk
# ----
# limits per-session temp file space in kB, or -1 for no limit
temp_file_limit = {{postgresql_temp_file_limit}}
# Kernel Resource Usage
# ---------------------
max_files_per_process = {{postgresql_max_files_per_process}} # min 25
shared_preload_libraries = '{{postgresql_shared_preload_libraries|join(',')}}'
# Cost-Based Vacuum Delay
# -----------------------
vacuum_cost_delay = {{postgresql_vacuum_cost_delay}} # 0-100 milliseconds
vacuum_cost_page_hit = {{postgresql_vacuum_cost_page_hit}} # 0-10000 credits
vacuum_cost_page_miss = {{postgresql_vacuum_cost_page_miss}} # 0-10000 credits
vacuum_cost_page_dirty = {{postgresql_vacuum_cost_page_dirty}} # 0-10000 credits
vacuum_cost_limit = {{postgresql_vacuum_cost_limit}} # 1-10000 credits
# Background Writer
# -----------------
bgwriter_delay = {{postgresql_bgwriter_delay}} # 10-10000ms between rounds
bgwriter_lru_maxpages = {{postgresql_bgwriter_lru_maxpages}} # 0-1000 max buffers written/round
bgwriter_lru_multiplier = {{postgresql_bgwriter_lru_multiplier}} # 0-10.0 multipler on buffers scanned/round
# Asynchronous Behavior
# ---------------------
effective_io_concurrency = {{postgresql_effective_io_concurrency}} # 1-1000; 0 disables prefetching
# Write Ahead Log
# ---------------
wal_level = {{postgresql_wal_level}} # minimal, archive, or hot_standby
fsync = {{'on' if postgresql_fsync else 'off'}} # turns forced synchronization on or off
# synchronization levels:
# - off
# - local
# - remote_write
# - on
{% if postgresql_synchronous_commit is string %}
synchronous_commit = {{postgresql_synchronous_commit}}
{% else %}
synchronous_commit = {{'on' if postgresql_synchronous_commit else 'off'}}
{% endif %}
# The default is the first option supported by the operating system:
# - open_datasync
# - fdatasync (default on Linux)
# - fsync
# - fsync_writethrough
# - open_sync
wal_sync_method = {{postgresql_wal_sync_method}}
# Recover from partial page writes
full_page_writes = {{'on' if postgresql_full_page_writes else 'off'}}
wal_buffers = {{postgresql_wal_buffers}} # min 32kB, -1 sets based on shared_buffers
wal_writer_delay = {{postgresql_wal_writer_delay}} # 1-10000 milliseconds
commit_delay = {{postgresql_commit_delay}} # range 0-100000, in microseconds
commit_siblings = {{postgresql_commit_siblings}} # range 1-1000
checkpoint_segments = {{postgresql_checkpoint_segments}} # in logfile segments, min 1, 16MB each
checkpoint_timeout = {{postgresql_checkpoint_timeout}} # range 30s-1h
checkpoint_completion_target = {{postgresql_checkpoint_completion_target}} # checkpoint target duration, 0.0 - 1.0
checkpoint_warning = {{postgresql_checkpoint_warning}} # 0 disables
archive_mode = {{'on' if postgresql_archive_mode else 'off'}} # allows archiving to be done
# Command to use to archive a logfile segment.
# Placeholders: %p = path of file to archive
# %f = file name only
# e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
archive_command = '{{postgresql_archive_command}}'
# force a logfile segment switch after this number of seconds
archive_timeout = {{postgresql_archive_timeout}} # 0 disables
# Replication
# -----------
# Set these on the master and on any standby that will send replication data.
max_wal_senders = {{postgresql_max_wal_senders}} # max number of walsender processes
wal_keep_segments = {{postgresql_wal_keep_segments}} # in logfile segments, 16MB each; 0 disables
wal_sender_timeout = {{postgresql_wal_sender_timeout}} # in milliseconds; 0 disables
# Replication (masters)
# ---------------------
# These settings are ignored on a standby server.
# Standby servers that provide sync rep.
# Comma-separated list of application_name from standby(s)
synchronous_standby_names = '{{postgresql_synchronous_standby_names|join(',')}}' # '*' means 'all'
# Number of xacts by which cleanup is delayed
vacuum_defer_cleanup_age = {{postgresql_vacuum_defer_cleanup_age}}
# Replication (standbys)
# ----------------------
# These settings are ignored on a master server.
# "on" allows queries during recovery
hot_standby = {{'on' if postgresql_hot_standby else 'off'}}
# max delay before canceling queries when reading WAL from archive
max_standby_archive_delay = {{postgresql_max_standby_archive_delay}} # -1 allows indefinite delay
# max delay before canceling queries when reading streaming WAL;
max_standby_streaming_delay = {{postgresql_max_standby_streaming_delay}} # -1 allows indefinite delay
# send replies at least this often
wal_receiver_status_interval = {{postgresql_wal_receiver_status_interval}} # 0 disables
# send info from standby to prevent query conflicts
hot_standby_feedback = {{'on' if postgresql_hot_standby_feedback or 'off'}}
#time that receiver waits for communication from master in milliseconds
wal_receiver_timeout = {{postgresql_wal_receiver_timeout}}
# Query Tuning (Planner)
# ----------------------
enable_bitmapscan = {{'on' if postgresql_enable_bitmapscan else 'off'}}
enable_hashagg = {{'on' if postgresql_enable_hashagg else 'off'}}
enable_hashjoin = {{'on' if postgresql_enable_hashjoin else 'off'}}
enable_indexscan = {{'on' if postgresql_enable_indexscan else 'off'}}
enable_indexonlyscan = {{'on' if postgresql_enable_indexonlyscan else 'off'}}
enable_material = {{'on' if postgresql_enable_material else 'off'}}
enable_mergejoin = {{'on' if postgresql_enable_mergejoin else 'off'}}
enable_nestloop = {{'on' if postgresql_enable_nestloop else 'off'}}
enable_seqscan = {{'on' if postgresql_enable_seqscan else 'off'}}
enable_sort = {{'on' if postgresql_enable_sort else 'off'}}
enable_tidscan = {{'on' if postgresql_enable_tidscan else 'off'}}
seq_page_cost = {{postgresql_seq_page_cost}} # measured on an arbitrary scale
random_page_cost = {{postgresql_random_page_cost}} # same scale as above
cpu_tuple_cost = {{postgresql_cpu_tuple_cost}} # same scale as above
cpu_index_tuple_cost = {{postgresql_cpu_index_tuple_cost}} # same scale as above
cpu_operator_cost = {{postgresql_cpu_operator_cost}} # same scale as above
effective_cache_size = {{postgresql_effective_cache_size}}
# Query Tuning (Genetic Query Optimizer)
# --------------------------------------
geqo = {{'on' if postgresql_enable_tidscan else 'off'}}
geqo_threshold = {{postgresql_geqo_threshold}}
geqo_effort = {{postgresql_geqo_effort}} # range 1-10
geqo_pool_size = {{postgresql_geqo_pool_size}} # selects default based on effort
geqo_generations = {{postgresql_geqo_generations}} # selects default based on effort
geqo_selection_bias = {{postgresql_geqo_selection_bias}} # range 1.5-2.0
geqo_seed = {{postgresql_geqo_seed}} # range 0.0-1.0
# Query Tuning (Other Planner Options)
# ------------------------------------
default_statistics_target = {{postgresql_default_statistics_target}} # range 1-10000
constraint_exclusion = {{postgresql_constraint_exclusion}} # on, off, or partition
cursor_tuple_fraction = {{postgresql_cursor_tuple_fraction}} # range 0.0-1.0
from_collapse_limit = {{postgresql_from_collapse_limit}}
join_collapse_limit = {{postgresql_join_collapse_limit}} # 1 disables collapsing of explicit JOIN clauses
# Error Reporting And Logging
# ---------------------------
# Valid values are combinations of stderr, csvlog, syslog, and eventlog.
# depending on platform. Csvlog requires logging_collector to be on.
log_destination = '{{postgresql_log_destination}}'
# Enable capturing of stderr and csvlog into log files.
# Required to be on for csvlogs.
logging_collector = {{'on' if postgresql_logging_collector else 'off'}}
# These are only used if logging_collector is on:
# Directory where log files are written, can be absolute or relative to PGDATA
log_directory = '{{postgresql_log_directory}}'
# Log file name pattern, can include strftime() escapes
log_filename = '{{postgresql_log_filename}}'
log_file_mode = {{postgresql_log_file_mode}} # begin with 0 to use octal notation
# If on, an existing log file with the same name as the new log file will be
# truncated rather than appended to. But such truncation only occurs on
# time-driven rotation, not on restarts or size-driven rotation. Default is
# off, meaning append to existing files in all cases.
log_truncate_on_rotation = {{'on' if postgresql_log_truncate_on_rotation else 'off'}}
# Automatic rotation of logfiles will happen after that time.
log_rotation_age = {{postgresql_log_rotation_age}} # 0 disables.
# Automatic rotation of logfiles will happen after that much log output.
log_rotation_size = {{postgresql_log_rotation_size}} # 0 disables.
# These are relevant when logging to syslog:
syslog_facility = '{{postgresql_syslog_facility}}'
syslog_ident = '{{postgresql_syslog_ident}}'
# This is only relevant when logging to eventlog (win32):
event_source = '{{postgresql_event_source}}'
# Values in order of decreasing detail:
# - debug5
# - debug4
# - debug3
# - debug2
# - debug1
# - log
# - notice
# - warning
# - error
client_min_messages = {{postgresql_client_min_messages}}
# Values in order of decreasing detail:
# - debug5
# - debug4
# - debug3
# - debug2
# - debug1
# - info
# - notice
# - warning
# - error
# - log
# - fatal
# - panic
log_min_messages = {{postgresql_log_min_messages}}
# Values in order of decreasing detail:
# - debug5
# - debug4
# - debug3
# - debug2
# - debug1
# - info
# - notice
# - warning
# - error
# - log
# - fatal
# - panic (effectively off)
log_min_error_statement = {{postgresql_log_min_error_statement}}
# -1 is disabled, 0 logs all statements and their durations, > 0 logs only
# statements running at least this number of milliseconds
log_min_duration_statement = {{postgresql_log_min_duration_statement}}
debug_print_parse = {{'on' if postgresql_debug_print_parse else 'off'}}
debug_print_rewritten = {{'on' if postgresql_debug_print_rewritten else 'off'}}
debug_print_plan = {{'on' if postgresql_debug_print_plan else 'off'}}
debug_pretty_print = {{'on' if postgresql_debug_pretty_print else 'off'}}
log_checkpoints = {{'on' if postgresql_log_checkpoints else 'off'}}
log_connections = {{'on' if postgresql_log_connections else 'off'}}
log_disconnections = {{'on' if postgresql_log_disconnections else 'off'}}
log_duration = {{'on' if postgresql_log_duration else 'off'}}
log_error_verbosity = {{postgresql_log_error_verbosity}} # terse, default, or verbose messages
log_hostname = {{'on' if postgresql_log_duration else 'off'}}
# special values:
# %a = application name
# %u = user name
# %d = database name
# %r = remote host and port
# %h = remote host
# %p = process ID
# %t = timestamp without milliseconds
# %m = timestamp with milliseconds
# %i = command tag
# %e = SQL state
# %c = session ID
# %l = session line number
# %s = session start timestamp
# %v = virtual transaction ID
# %x = transaction ID (0 if none)
# %q = stop here in non-session
# processes
# %% = '%'
log_line_prefix = '{{postgresql_log_line_prefix}}'
# log lock waits >= deadlock_timeout
log_lock_waits = {{'on' if postgresql_log_lock_waits else 'off'}}
log_statement = '{{postgresql_log_statement}}' # none, ddl, mod, all
# log temporary files equal or larger than the specified size in kilobytes
log_temp_files = {{postgresql_log_temp_files}} # -1 disables, 0 logs all temp files
log_timezone = '{{postgresql_log_timezone}}'
# Runtime statistics
# ------------------
track_activities = {{'on' if postgresql_track_activities else 'off'}}
track_counts = {{'on' if postgresql_track_counts else 'off'}}
track_io_timing = {{'on' if postgresql_track_io_timing else 'off'}}
track_functions = {{postgresql_track_functions}} # none, pl, all
track_activity_query_size = {{postgresql_track_activity_query_size}}
update_process_title = {{'on' if postgresql_update_process_title else 'off'}}
stats_temp_directory = '{{postgresql_stats_temp_directory}}'
log_parser_stats = {{'on' if postgresql_log_parser_stats else 'off'}}
log_planner_stats = {{'on' if postgresql_log_planner_stats else 'off'}}
log_executor_stats = {{'on' if postgresql_log_executor_stats else 'off'}}
log_statement_stats = {{'on' if postgresql_log_statement_stats else 'off'}}
# Autovacuum Parameters
# ---------------------
# Enable autovacuum subprocess? 'on' requires track_counts to also be on.
autovacuum = {{'on' if postgresql_autovacuum else 'off'}}
# -1 disables, 0 logs all actions and their durations, > 0 logs only
# actions running at least this number of milliseconds.
log_autovacuum_min_duration = {{postgresql_log_autovacuum_min_duration}}
# max number of autovacuum subprocesses
autovacuum_max_workers = {{postgresql_autovacuum_max_workers}}
# time between autovacuum runs
autovacuum_naptime = {{postgresql_autovacuum_naptime}}
# min number of row updates before vacuum
autovacuum_vacuum_threshold = {{postgresql_autovacuum_vacuum_threshold}}
# min number of row updates before analyze
autovacuum_analyze_threshold = {{postgresql_autovacuum_analyze_threshold}}
# fraction of table size before vacuum
autovacuum_vacuum_scale_factor = {{postgresql_autovacuum_vacuum_scale_factor}}
# fraction of table size before analyze
autovacuum_analyze_scale_factor = {{postgresql_autovacuum_analyze_scale_factor}}
# maximum XID age before forced vacuum
autovacuum_freeze_max_age = {{postgresql_autovacuum_freeze_max_age}}
# default vacuum cost delay for autovacuum, in milliseconds
autovacuum_vacuum_cost_delay = {{postgresql_autovacuum_vacuum_cost_delay}} # -1 means use vacuum_cost_delay
# default vacuum cost limit for autovacuum
autovacuum_vacuum_cost_limit = {{postgresql_autovacuum_vacuum_cost_limit}} # -1 means use vacuum_cost_limit
# Client Connection Defaults
# --------------------------
search_path = '{{postgresql_search_path|join(',')}}' # schema names
default_tablespace = '{{postgresql_default_tablespace}}' # '' uses the default
temp_tablespaces = '{{postgresql_temp_tablespaces|join(',')}}' # '' uses only default tablespace
check_function_bodies = {{'on' if postgresql_check_function_bodies else 'off'}}
default_transaction_isolation = '{{postgresql_default_transaction_isolation}}'
default_transaction_read_only = {{'on' if postgresql_default_transaction_read_only else 'off'}}
default_transaction_deferrable = {{'on' if postgresql_default_transaction_deferrable else 'off'}}
session_replication_role = '{{postgresql_session_replication_role}}'
statement_timeout = {{postgresql_statement_timeout}} # in milliseconds, 0 is disabled
lock_timeout = {{postgresql_lock_timeout}} # in milliseconds, 0 is disabled
vacuum_freeze_min_age = {{postgresql_vacuum_freeze_min_age}}
vacuum_freeze_table_age = {{postgresql_vacuum_freeze_table_age}}
bytea_output = '{{postgresql_bytea_output}}' # hex, escape
xmlbinary = '{{postgresql_xmlbinary}}'
xmloption = '{{postgresql_xmloption}}'
datestyle = '{{postgresql_datestyle|join(',')}}'
intervalstyle = '{{postgresql_intervalstyle}}'
timezone = '{{postgresql_timezone}}'
# Select the set of available time zone abbreviations. Currently, there are:
# - Default
# - Australia
# - India
# You can create your own file in `share/timezonesets/`.
timezone_abbreviations = '{{postgresql_timezone_abbreviations}}'
extra_float_digits = {{postgresql_extra_float_digits}} # min -15, max 3
client_encoding = {{postgresql_client_encoding}} # 'sql_ascii' actually defaults to database encoding
# These settings are initialized by initdb, but they can be changed.
# locale for system error message strings
lc_messages = '{{postgresql_lc_messages}}'
# locale for monetary formatting
lc_monetary = '{{postgresql_lc_monetary}}'
# locale for number formatting
lc_numeric = '{{postgresql_lc_numeric}}'
# locale for time formatting
lc_time = '{{postgresql_lc_time}}'
# default configuration for text search
default_text_search_config = '{{postgresql_default_text_search_config}}'
dynamic_library_path = '{{postgresql_dynamic_library_path}}'
local_preload_libraries = '{{postgresql_local_preload_libraries|join(',')}}'
# Lock Management
# ---------------
deadlock_timeout = {{postgresql_deadlock_timeout}}
max_locks_per_transaction = {{postgresql_max_locks_per_transaction}} # min 10
# Note: Each lock table slot uses ~270 bytes of shared memory, and there are
# max_locks_per_transaction * (max_connections + max_prepared_transactions)
# lock table slots.
max_pred_locks_per_transaction = {{postgresql_max_pred_locks_per_transaction}} # min 10
# Version/platform Compatibility
# ------------------------------
array_nulls = {{'on' if postgresql_array_nulls else 'off'}}
backslash_quote = {{postgresql_backslash_quote}} # on, off, or safe_encoding
default_with_oids = {{'on' if postgresql_default_with_oids else 'off'}}
escape_string_warning = {{'on' if postgresql_escape_string_warning else 'off'}}
lo_compat_privileges = {{'on' if postgresql_lo_compat_privileges else 'off'}}
quote_all_identifiers = {{'on' if postgresql_quote_all_identifiers else 'off'}}
sql_inheritance = {{'on' if postgresql_sql_inheritance else 'off'}}
standard_conforming_strings = {{'on' if postgresql_standard_conforming_strings else 'off'}}
synchronize_seqscans = {{'on' if postgresql_synchronize_seqscans else 'off'}}
transform_null_equals = {{'on' if postgresql_transform_null_equals else 'off'}}
# Error Handling
# --------------
# Terminate session on any error?
exit_on_error = {{'on' if postgresql_exit_on_error else 'off'}}
# Reinitialize after backend crash?
restart_after_crash = {{'on' if postgresql_restart_after_crash else 'off'}}
# Config File Includes
# --------------------
# These options allow settings to be loaded from files other than the
# default postgresql.conf.
# include files ending in '.conf' from directory 'conf.d'
#include_dir = 'conf.d'
# include file only if it exists
#include_if_exists = 'exists.conf'
# include file
#include = 'special.conf'
# CUSTOMIZED OPTIONS
# ------------------
# Add settings for extensions here

24
provision/roles/zenoamaro.postgresql/test.yml

@ -0,0 +1,24 @@
# Integration testing playbook
# ----------------------------
# A playbook for testing and integration.
# It will provision the `test` hosts in the inventory,
# which will, by default, specify the provided vagrant VM.
# This playbook should aim to test the most extensive
# or comprehensive configuration possible for your role.
- name: 'Role integration tests'
hosts: test
vars:
postgresql_dev_headers: yes
postgresql_contrib: yes
postgresql_postgis: yes
roles:
- '.' # The current directory itself is the role

1
provision/site.retry

@ -0,0 +1 @@
default

18
provision/site.yml

@ -0,0 +1,18 @@
---
- name: Base tasks
hosts: [development, staging, production]
remote_user: root
roles:
- common
- zenoamaro.postgresql
- python
- database
- app
- name: Deployment tasks
hosts: [production]
remote_user: root
roles:
- deploy-code
- supervisor
- nginx

18
provision/templates/humans.txt

@ -0,0 +1,18 @@
# humanstxt.org/
# The humans responsible & technology colophon
# TEAM
Electric Umbrella
Drew Larson -- Lead -- @drwlrsn
# THANKS
<name>
# TECHNOLOGY COLOPHON
HTML5, CSS3
jQuery, Modernizr,
Django, Wagtail,
Satchless, SASS,
Bourbon

3
provision/templates/pg_hba.conf

@ -0,0 +1,3 @@
local all postgres peer
local all vagrant peer
local all {{ db_user }} peer

8
requirements/base.txt

@ -0,0 +1,8 @@
Django==1.9.4
pytz==2015.7
django-widget-tweaks==1.4.1
psycopg2==2.6.1
celery[redis]==3.1.23
django-celery==3.1.17
opbeat==3.3
django-tz-detect==0.2.6

4
requirements/development.txt

@ -0,0 +1,4 @@
-r base.txt
-r testing.txt
django-debug-toolbar
PyYAML

2
requirements/production.txt

@ -0,0 +1,2 @@
-r base.txt
gunicorn==19.4.5

1
requirements/staging.txt

@ -0,0 +1 @@
-r production.txt

2
requirements/testing.txt

@ -0,0 +1,2 @@
coverage
mock
Loading…
Cancel
Save