This commit is contained in:
noelmcloughlin 2018-03-26 09:44:31 +01:00
commit b3be3de843
25 changed files with 905 additions and 728 deletions

View file

@ -16,17 +16,56 @@ Available states
``postgres``
------------
Installs the PostgreSQL server package and prepares the DB cluster.
Installs and configures both PostgreSQL server and client with creation of various DB objects in
the cluster. This state applies to both Linux and MacOS.
``postgres.client``
-------------------
Installs the PostgreSQL client binaries and libraries.
Installs the PostgreSQL client binaries and libraries on Linux.
``postgres.manage``
-------------------
Creates such DB objects as: users, tablespaces, databases, schemas and extensions.
See ``pillar.example`` file for details.
``postgres.python``
-------------------
Installs the PostgreSQL adapter for Python.
Installs the PostgreSQL adapter for Python on Linux.
``postgres.server``
-------------------
Installs the PostgreSQL server package on Linux, prepares the DB cluster and starts the server using
packaged init script, job or unit.
``postgres.server.image``
-------------------------
Installs the PostgreSQL server package on Linux, prepares the DB cluster and starts the server by issuing
raw ``pg_ctl`` command. The ``postgres:bake_image`` Pillar toggles this behaviour. For example:
.. code:: yaml
postgres:
bake_image: True
If set ``True``, then it becomes possible to fully provision PostgreSQL with all supported entities
from ``postgres.manage`` state during the build ("baking") of AMI / VM / Container images (using
Packer, Docker or similar tools), i.e. when OS ``init`` process is not available to start the
service and enable it on "boot" of resulting appliance.
Also it allows to make Docker images with PostgreSQL using functionality being available since Salt
2016.11.0 release:
.. code:: console
salt 'minion.with.docker' dockerng.sls_build my-postgres base=centos/systemd mods=postgres
If a lookup dictionary or Pillar has ``postgres:bake_image`` set ``False`` (this is default), it is
equivalent of applying ``postgres.server`` state.
``postgres.upstream``
---------------------
@ -34,17 +73,19 @@ Installs the PostgreSQL adapter for Python.
Configures the PostgreSQL Official (upstream) repository on target system if
applicable.
The state relies on the ``postgres:use_upstream_repo`` Pillar value which could
be set as following:
The state relies on the ``postgres:use_upstream_repo`` Pillar value which could be set as following:
* ``True`` (default): adds the upstream repository to install packages from
* ``False``: makes sure that the repository configuration is absent
* ``'postgresapp'`` (MacOS) uses upstream PostgresApp package repository.
* ``'homebrew'`` (MacOS) uses Homebrew postgres
The ``postgres:version`` Pillar controls which version of the PostgreSQL
packages should be installed from the upstream repository. Defaults to ``9.5``.
The ``postgres:version`` Pillar controls which version of the PostgreSQL packages should be
installed from the upstream Linux repository. Defaults to ``9.5``.
Testing
=======
The postgres state was tested on MacOS (El Capitan 10.11.6)
Testing is done with the ``kitchen-salt``.
@ -67,3 +108,5 @@ Builds and runs tests from scratch.
-----------------
Gives you ssh to the vagrant machine for manual testing.
.. vim: fenc=utf-8 spell spl=en cc=100 tw=99 fo=want sts=2 sw=2 et

View file

@ -1,257 +0,0 @@
from __future__ import absolute_import
import logging
try:
import pipes
import csv
HAS_ALL_IMPORTS = True
except ImportError:
HAS_ALL_IMPORTS = False
# All this can be removed when we merge this stuff upstream
import salt.utils
log = logging.getLogger(__name__)
def __virtual__():
'''
Only load this module if the postgres module is already loaded
'''
if all((salt.utils.which('psql'), HAS_ALL_IMPORTS)):
return True
return False
# Copied directly from salt/modules/postgres.py, remove when upstreaming
def _run_psql(cmd, runas=None, password=None, host=None, port=None, user=None):
'''
Helper function to call psql, because the password requirement
makes this too much code to be repeated in each function below
'''
kwargs = {
'reset_system_locale': False,
'clean_env': True,
}
if runas is None:
if not host:
host = __salt__['config.option']('postgres.host')
if user is None:
user = runas
if runas:
kwargs['runas'] = runas
if password is None:
password = __salt__['config.option']('postgres.pass')
if password is not None:
pgpassfile = salt.utils.mkstemp(text=True)
with salt.utils.fopen(pgpassfile, 'w') as fp_:
fp_.write('{0}:{1}:*:{2}:{3}'.format(
'localhost' if not host or host.startswith('/') else host,
port if port else '*',
user if user else '*',
password,
))
__salt__['file.chown'](pgpassfile, runas, '')
kwargs['env'] = {'PGPASSFILE': pgpassfile}
ret = __salt__['cmd.run_all'](cmd, python_shell=False, **kwargs)
if ret.get('retcode', 0) != 0:
log.error('Error connecting to Postgresql server')
if password is not None and not __salt__['file.remove'](pgpassfile):
log.warning('Remove PGPASSFILE failed')
return ret
def _connection_defaults(user=None, host=None, port=None, maintenance_db=None,
password=None):
'''
Returns a tuple of (user, host, port, db) with config, pillar, or default
values assigned to missing values.
'''
if not user:
user = __salt__['config.option']('postgres.user')
if not host:
host = __salt__['config.option']('postgres.host')
if not port:
port = __salt__['config.option']('postgres.port')
if not maintenance_db:
maintenance_db = __salt__['config.option']('postgres.maintenance_db')
if password is None:
password = __salt__['config.option']('postgres.pass')
return (user, host, port, maintenance_db, password)
def _psql_cmd(*args, **kwargs):
'''
Return string with fully composed psql command.
Accept optional keyword arguments: user, host and port as well as any
number or positional arguments to be added to the end of command.
'''
(user, host, port, maintenance_db, password) = _connection_defaults(
kwargs.get('user'),
kwargs.get('host'),
kwargs.get('port'),
kwargs.get('maintenance_db'),
kwargs.get('password'))
cmd = [salt.utils.which('psql'),
'--no-align',
'--no-readline',
'--no-password'] # It is never acceptable to issue a password prompt.
if user:
cmd += ['--username', user]
if host:
cmd += ['--host', host]
if port:
cmd += ['--port', str(port)]
if not maintenance_db:
maintenance_db = 'postgres'
cmd += ['--dbname', maintenance_db]
cmd += args
cmdstr = ' '.join([pipes.quote(c) for c in cmd])
return cmdstr
def _psql_prepare_and_run(cmd,
host=None,
port=None,
maintenance_db=None,
password=None,
runas=None,
user=None):
rcmd = _psql_cmd(
host=host, user=user, port=port,
maintenance_db=maintenance_db, password=password,
*cmd)
cmdret = _run_psql(
rcmd, runas=runas, password=password, host=host, port=port, user=user)
return cmdret
def tablespace_list(user=None, host=None, port=None, maintenance_db=None,
password=None, runas=None):
'''
Return dictionary with information about tablespaces of a Postgres server.
CLI Example:
.. code-block:: bash
salt '*' postgres_ext.tablespace_list
'''
ret = {}
query = (
'SELECT spcname as "Name", pga.rolname as "Owner", spcacl as "ACL", '
'spcoptions as "Opts", pg_tablespace_location(pgts.oid) as "Location" '
'FROM pg_tablespace pgts, pg_roles pga WHERE pga.oid = pgts.spcowner'
)
rows = __salt__['postgres.psql_query'](query, runas=runas, host=host,
user=user, port=port,
maintenance_db=maintenance_db,
password=password)
for row in rows:
ret[row['Name']] = row
ret[row['Name']].pop('Name')
return ret
def tablespace_exists(name, user=None, host=None, port=None, maintenance_db=None,
password=None, runas=None):
'''
Checks if a tablespace exists on the Postgres server.
CLI Example:
.. code-block:: bash
salt '*' postgres_ext.tablespace_exists 'dbname'
'''
tablespaces = tablespace_list(user=user, host=host, port=port,
maintenance_db=maintenance_db,
password=password, runas=runas)
return name in tablespaces
def tablespace_create(name, location, owner=None, user=None, host=None, port=None,
maintenance_db=None, password=None, runas=None):
'''
Adds a tablespace to the Postgres server.
CLI Example:
.. code-block:: bash
salt '*' postgres_ext.tablespace_create tablespacename '/path/datadir'
'''
query = 'CREATE TABLESPACE "{0}" LOCATION \'{1}\''.format(name, location)
if owner is not None:
query += ' OWNER "{1}"'.format(owner)
# Execute the command
ret = _psql_prepare_and_run(['-c', query],
user=user, host=host, port=port,
maintenance_db=maintenance_db,
password=password, runas=runas)
return ret['retcode'] == 0
def tablespace_alter(name, user=None, host=None, port=None, maintenance_db=None,
password=None, new_name=None, new_owner=None,
set_option=None, reset_option=None, runas=None):
'''
Change tablespace name, owner, or options.
CLI Example:
.. code-block:: bash
salt '*' postgres_ext.tablespace_alter tsname new_owner=otheruser
salt '*' postgres_ext.tablespace_alter index_space new_name=fast_raid
salt '*' postgres_ext.tablespace_alter tsname reset_option=seq_page_cost
'''
if not any([new_name, new_owner, set_option, reset_option]):
return True # Nothing todo?
queries = []
if new_name:
queries.append('ALTER TABLESPACE "{}" RENAME TO "{}"'.format(
name, new_name))
if new_owner:
queries.append('ALTER TABLESPACE "{}" OWNER TO "{}"'.format(
name, new_owner))
if set_option:
queries.append('ALTER TABLESPACE "{}" SET ({} = {})'.format(
name, set_option[0], set_option[1]))
if reset_option:
queries.append('ALTER TABLESPACE "{}" RESET ({})'.format(
name, reset_option))
for query in queries:
ret = _psql_prepare_and_run(['-c', query],
user=user, host=host, port=port,
maintenance_db=maintenance_db,
password=password, runas=runas)
if ret['retcode'] != 0:
return False
return True
def tablespace_remove(name, user=None, host=None, port=None,
maintenance_db=None, password=None, runas=None):
'''
Removes a tablespace from the Postgres server.
CLI Example:
.. code-block:: bash
salt '*' postgres_ext.tablespace_remove tsname
'''
query = 'DROP TABLESPACE "{}"'.format(name)
ret = _psql_prepare_and_run(['-c', query],
user=user,
host=host,
port=port,
runas=runas,
maintenance_db=maintenance_db,
password=password)
return ret['retcode'] == 0

View file

@ -1,144 +0,0 @@
'''
Management of PostgreSQL tablespace
==================================
The postgres_tablespace module is used to create and manage Postgres
tablespaces.
Tablespaces can be set as either absent or present.
.. code-block:: yaml
ssd-tablespace:
postgres_tablespace.present:
- name: indexes
- path:
'''
from __future__ import absolute_import
def __virtual__():
'''
Only load if the postgres_ext module is present
'''
return 'postgres_ext.tablespace_exists' in __salt__
def present(name,
directory,
options=None,
owner=None,
user=None,
maintenance_db=None,
db_password=None,
db_host=None,
db_port=None,
db_user=None):
'''
Ensure that the named tablespace is present with the specified properties.
For more information about all of these options see man create_tablespace(1)
name
The name of the tablespace to manage
directory
The directory where the tablespace will be located
db_user
database username if different from config or defaul
db_password
user password if any password for a specified user
db_host
Database host if different from config or default
db_port
Database port if different from config or default
user
System user all operations should be performed on behalf of
.. versionadded:: Beryllium
'''
ret = {'name': name,
'changes': {},
'result': True,
'comment': 'Tablespace {0} is already present'.format(name)}
dbargs = {
'maintenance_db': maintenance_db,
'runas': user,
'host': db_host,
'user': db_user,
'port': db_port,
'password': db_password,
}
tblspaces = __salt__['postgres_ext.tablespace_list'](**dbargs)
if name not in tblspaces:
# not there, create it
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'Tablespace {0} is set to be created'.format(name)
return ret
if __salt__['postgres_ext.tablespace_create'](name, directory, **dbargs):
ret['comment'] = 'The tablespace {0} has been created'.format(name)
ret['changes'][name] = 'Present'
return ret
# already exists, make sure it's got the right path
if tblspaces[name]['Location'] != directory:
ret['comment'] = 'Tablespace {0} isn\'t at the right path'.format(
name)
ret['result'] = False
return ret # This isn't changeable, they need to remove/remake
if (owner and not tblspaces[name]['Owner'] == owner):
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'Tablespace {0} owner to be altered'.format(name)
return ret
if __salt__['postgres_ext.tablespace_alter'](name, new_owner=owner):
ret['comment'] = 'Tablespace {0} owner changed'.format(name)
ret['result'] = True
return ret
def absent(name,
user=None,
maintenance_db=None,
db_password=None,
db_host=None,
db_port=None,
db_user=None):
'''
Ensure that the named database is absent
name
The name of the database to remove
db_user
database username if different from config or defaul
db_password
user password if any password for a specified user
db_host
Database host if different from config or default
db_port
Database port if different from config or default
user
System user all operations should be performed on behalf of
.. versionadded:: Beryllium
'''
ret = {'name': name,
'changes': {},
'result': True,
'comment': ''}
db_args = {
'maintenance_db': maintenance_db,
'runas': user,
'host': db_host,
'user': db_user,
'port': db_port,
'password': db_password,
}
#check if tablespace exists and remove it
if __salt__['postgres_ext.tablespace_exists'](name, **db_args):
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'Tablespace {0} is set to be removed'.format(name)
return ret
if __salt__['postgres_ext.tablespace_remove'](name, **db_args):
ret['comment'] = 'Tablespace {0} has been removed'.format(name)
ret['changes'][name] = 'Absent'
return ret
# fallback
ret['comment'] = 'Tablespace {0} is not present, so it cannot ' \
'be removed'.format(name)
return ret

View file

@ -1,22 +1,43 @@
postgres:
# Set True to configure upstream postgresql.org repository for YUM or APT
# UPSTREAM REPO
# Set True to configure upstream postgresql.org repository for YUM/APT/ZYPP
use_upstream_repo: False
# Version to install from upstream repository
version: '9.3'
# Version to install from upstream repository (if upstream_repo: True)
version: '9.6'
# These are Debian/Ubuntu specific package names
pkg: 'postgresql-9.3'
pkg_client: 'postgresql-client-9.3'
### MACOS
# Set to 'postgresapp' OR 'homebrew' for MacOS
#use_upstream_repo: 'postgresapp'
#use_upstream_repo: 'homebrew'
# Addtional packages to install, this should be in a list format
# PACKAGE
# These pillars are typically never required.
# pkg: 'postgresql'
# pkg_client: 'postgresql-client'
# service: postgresql
pkgs_extra:
- postgresql-contrib
- postgresql-plpython
#'Alternatives system' priority incremental. 0 disables feature.
linux:
altpriority: 30
# macos limits
limits:
soft: 64000
hard: 64000
# POSTGRES
# Append the lines under this item to your postgresql.conf file.
# Pay attention to indent exactly with 4 spaces for all lines.
postgresconf: |
listen_addresses = '*' # listen on all interfaces
# Path to the `pg_hba.conf` file Jinja template on Salt Fileserver
pg_hba.conf: salt://postgres/templates/pg_hba.conf.j2
# This section covers ACL management in the `pg_hba.conf` file.
# This section covers ACL management in the ``pg_hba.conf`` file.
# acls list 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:
@ -29,17 +50,39 @@ postgres:
#
# The uppercase items must be replaced by actual values.
# METHOD could be omitted, 'md5' will be appended by default.
#
# If ``acls`` item value is empty ('', [], null), then the contents of
# ``pg_hba.conf`` file will not be touched at all.
acls:
- ['local', 'db0', 'connuser', 'peer map=users_as_appuser']
- ['local', 'db1', 'localUser']
- ['host', 'db2', 'remoteUser', '192.168.33.0/24']
# PostgreSQL service name
service: postgresql
identity_map:
- ['users_as_appuser', 'jdoe', 'connuser']
- ['users_as_appuser', 'jsmith', 'connuser']
# Backup extension for configuration files, defaults to ``.bak``.
# Set ``False`` to stop creation of backups when config files change.
{%- if salt['status.time']|default(none) is callable %}
config_backup: ".backup@{{ salt['status.time']('%y-%m-%d_%H:%M:%S') }}"
{%- endif %}
{%- if grains['init'] == 'unknown' %}
# If Salt is unable to detect init system running in the scope of state run,
# probably we are trying to bake a container/VM image with PostgreSQL.
# Use ``bake_image`` setting to control how PostgreSQL will be started: if set
# to ``True`` the raw ``pg_ctl`` will be utilized instead of packaged init
# script, job or unit run with Salt ``service`` state.
bake_image: True
{%- endif %}
# Create/remove users, tablespaces, databases, schema and extensions.
# Each of these dictionaries contains PostgreSQL entities which
# mapped to the `postgres_*` Salt states with arguments. See the Salt
# documentaion to get all supported argument for a particular state.
# mapped to the ``postgres_*`` Salt states with arguments. See the Salt
# documentation to get all supported argument for a particular state.
#
# Format is the following:
#
@ -86,11 +129,13 @@ postgres:
absentUser:
ensure: absent
# tablespaces to be created
tablespaces:
my_space:
directory: /srv/my_tablespace
owner: localUser
# databases to be created
databases:
db1:
owner: 'localUser'
@ -103,6 +148,14 @@ postgres:
lc_ctype: 'en_US.UTF-8'
lc_collate: 'en_US.UTF-8'
tablespace: 'my_space'
# set custom schema
schemas:
public:
owner: 'localUser'
# enable per-db extension
extensions:
uuid-ossp:
schema: 'public'
# optional schemas to enable on database
schemas:
@ -117,11 +170,4 @@ postgres:
maintenance_db: db1
#postgis: {}
# Backup extension defaults to .bak if postgresconf_backup is True.
# Set to False to stop creation of backup on postgresql.conf changes.
postgresconf_backup: True
# This section will append your configuration to postgresql.conf.
postgresconf: |
listen_addresses = 'localhost,*'
# vim: ft=yaml:sw=2
# vim: ft=yaml ts=2 sts=2 sw=2 et

View file

@ -1,21 +1,40 @@
{% from "postgres/map.jinja" import postgres with context %}
{%- from "postgres/map.jinja" import postgres with context -%}
{% if postgres.use_upstream_repo %}
{%- set pkgs = [] %}
{%- for pkg in (postgres.pkg_client, postgres.pkg_libpq_dev) %}
{%- if pkg %}
{%- do pkgs.append(pkg) %}
{%- endif %}
{%- endfor %}
{%- if postgres.use_upstream_repo == true %}
include:
- postgres.upstream
{% endif %}
install-postgresql-client:
pkg.installed:
- name: {{ postgres.pkg_client }}
- refresh: {{ postgres.use_upstream_repo }}
{% if postgres.use_upstream_repo %}
- require:
- pkgrepo: install-postgresql-repo
{%- endif %}
{% if postgres.pkg_libpq_dev %}
install-postgres-libpq-dev:
# Install PostgreSQL client and libraries
postgresql-client-libs:
pkg.installed:
- name: {{ postgres.pkg_libpq_dev }}
{% endif %}
- pkgs: {{ pkgs }}
{%- if postgres.use_upstream_repo == true %}
- refresh: True
- require:
- pkgrepo: postgresql-repo
{%- endif %}
# Alternatives system. Make client binaries available in $PATH
{%- if 'bin_dir' in postgres and postgres.linux.altpriority %}
{%- for bin in postgres.client_bins %}
{%- set path = salt['file.join'](postgres.bin_dir, bin) %}
{{ bin }}:
alternatives.install:
- link: {{ salt['file.join']('/usr/bin', bin) }}
- path: {{ path }}
- priority: {{ postgres.linux.altpriority }}
- onlyif: test -f {{ path }}
- require:
- pkg: postgresql-client-libs
{%- endfor %}
{%- endif %}

View file

@ -16,7 +16,7 @@
#}
{# use upstream version if configured #}
{% if repo.use_upstream_repo %}
{% if repo.use_upstream_repo == true %}
{% set version = repo.version %}
{% endif %}
@ -31,18 +31,45 @@
command: pg_createcluster {{ version }} main
test: test -f /var/lib/postgresql/{{ version }}/main/PG_VERSION && test -f /etc/postgresql/{{ version }}/main/postgresql.conf
user: root
env: {}
{% endmacro %}
{% macro fedora_codename(name, version, codename=none) %}
{#
Generate lookup dictionary map for Fedora distributions
name:
distro codename
version:
PostgreSQL release version
codename:
optional grain value if `name` does not match the one returned by
`oscodename` grain
#}
{# use upstream version if configured #}
{% if repo.use_upstream_repo == true %}
{% set version = repo.version %}
{% endif %}
{{ codename|default(name, true) }}:
# PostgreSQL packages are mostly downloaded from `main` repo component
pkg_repo:
baseurl: 'https://download.postgresql.org/pub/repos/yum/{{ version }}/fedora/fedora-$releasever-$basearch'
{% endmacro %}
## Debian GNU/Linux
{{ debian_codename('wheezy', '9.1') }}
{{ debian_codename('jessie', '9.4') }}
{{ debian_codename('stretch', '9.6') }}
# `oscodename` grain has long distro name
# if `lsb-release` package not installed
{{ debian_codename('wheezy', '9.1', 'Debian GNU/Linux 7 (wheezy)') }}
{{ debian_codename('jessie', '9.4', 'Debian GNU/Linux 8 (jessie)') }}
{{ debian_codename('stretch', '9.6', 'Debian GNU/Linux 9 (stretch)') }}
## Ubuntu
{{ debian_codename('trusty', '9.3') }}
@ -52,4 +79,10 @@
{{ debian_codename('wily', '9.4') }}
{{ debian_codename('xenial', '9.5') }}
## Fedora
# `oscodename` grain has long distro name
{{ fedora_codename('Fedora-25', '9.5', 'Fedora 25 (Twenty Five)') }}
{{ fedora_codename('Fedora-24', '9.5', 'Fedora 24 (Twenty Four)') }}
{{ fedora_codename('Fedora-23', '9.4', 'Fedora 23 (Twenty Three)') }}
# vim: ft=sls

View file

@ -7,11 +7,37 @@ postgres:
pkgs_extra: []
pkg_client: postgresql-client
pkg_dev: postgresql-devel
pkg_libpq_dev: postgresql-libs
python: python-psycopg2
pkg_libpq_dev: libpq-dev
pkg_libs: postgresql-libs
pkg_python: python-psycopg2
userhomes: /home
user: postgres
group: postgres
prepare_cluster:
command: initdb --pgdata=/var/lib/pgsql/data
test: test -f /var/lib/pgsql/data/PG_VERSION
user: postgres
env: []
conf_dir: /var/lib/pgsql/data
postgresconf: ""
macos:
archive: postgres.dmg
tmpdir: /tmp/postgrestmp
postgresapp:
#See: https://github.com/PostgresApp/PostgresApp/releases/
url: https://github.com/PostgresApp/PostgresApp/releases/download/v2.1.1/Postgres-2.1.1.dmg
sum: sha256=ac0656b522a58fd337931313f09509c09610c4a6078fe0b8e469e69af1e1750b
homebrew:
url:
sum:
dl:
opts: -s -L
interval: 60
retries: 2
pg_hba.conf: salt://postgres/templates/pg_hba.conf.j2
acls:
# "local" is for Unix domain socket connections only
@ -20,22 +46,22 @@ postgres:
- ['host', 'all', 'all', '127.0.0.1/32', 'md5']
# IPv6 local connections:
- ['host', 'all', 'all', '::1/128', 'md5']
pg_ident.conf: salt://postgres/templates/pg_ident.conf.j2
identity_map: []
config_backup: '.bak'
service: postgresql
bake_image: False
users: {}
tablespaces: {}
databases: {}
schemas: {}
extensions: {}
postgresconf_backup: True
postgresconf: ""
# if prepare_cluster is over-ridden in any of:
# - osmap.yaml
# - oscodenamemap.yaml
# - osfingermap.yaml
# you will have to specify a complete dictionary.
prepare_cluster:
user: root
command: service postgresql initdb
test: test -f /var/lib/pgsql/data/PG_VERSION
env: {}
linux:
#Alternatives system are disabled by a 'altpriority=0' pillar.
altpriority:

View file

@ -1,13 +1,59 @@
{% from "postgres/map.jinja" import postgres with context %}
{% if postgres.pkg_dev %}
{% if grains.os not in ('Windows', 'MacOS',) %}
{% if postgres.pkg_dev %}
install-postgres-dev-package:
pkg.installed:
- name: {{ postgres.pkg_dev }}
{% endif %}
{% endif %}
{% if postgres.pkg_libpq_dev %}
{% if postgres.pkg_libpq_dev %}
install-postgres-libpq-dev:
pkg.installed:
- name: {{ postgres.pkg_libpq_dev }}
{% endif %}
{% endif %}
{% if grains.os == 'MacOS' %}
# Darwin maxfiles limits
{% if postgres.limits.soft or postgres.limits.hard %}
postgres_maxfiles_limits_conf:
file.managed:
- name: /Library/LaunchDaemons/limit.maxfiles.plist
- source: salt://postgres/templates/limit.maxfiles.plist
- context:
soft_limit: {{ postgres.limits.soft or postgres.limits.hard }}
hard_limit: {{ postgres.limits.hard or postgres.limits.soft }}
- group: {{ postgres.group }}
{% endif %}
{% if postgres.use_upstream_repo == 'postgresapp' %}
# Shortcut for PostgresApp
postgres-desktop-shortcut-clean:
file.absent:
- name: '{{ postgres.userhomes }}/{{ postgres.user }}/Desktop/Postgres ({{ postgres.use_upstream_repo }})'
- require_in:
- file: postgres-desktop-shortcut-add
postgres-desktop-shortcut-add:
file.managed:
- name: /tmp/mac_shortcut.sh
- source: salt://postgres/templates/mac_shortcut.sh
- mode: 755
- template: jinja
- context:
user: {{ postgres.user }}
homes: {{ postgres.userhomes }}
cmd.run:
- name: '/tmp/mac_shortcut.sh "Postgres ({{ postgres.use_upstream_repo }})"'
- runas: {{ postgres.user }}
- require:
- file: postgres-desktop-shortcut-add
{% endif %}
{% endif %}

View file

@ -1,181 +1,9 @@
# -*- mode: yaml -*-
{%- from "postgres/map.jinja" import postgres with context -%}
{%- from "postgres/macros.jinja" import format_state with context -%}
{%- if postgres.use_upstream_repo %}
include:
- postgres.upstream
{%- endif %}
### Installation states
postgresql-installed:
pkg.installed:
- name: {{ postgres.pkg }}
- refresh: {{ postgres.use_upstream_repo }}
{% if postgres.use_upstream_repo %}
- require:
- pkgrepo: install-postgresql-repo
{%- endif %}
# make sure the data directory and contents have been initialized
postgresql-cluster-prepared:
cmd.run:
- name: {{ postgres.prepare_cluster.command }}
- cwd: /
- runas: {{ postgres.prepare_cluster.user }}
- env: {{ postgres.prepare_cluster.env|default({}) }}
- unless:
- {{ postgres.prepare_cluster.test }}
- require:
- pkg: postgresql-installed
postgresql-config-dir:
file.directory:
- name: {{ postgres.conf_dir }}
- user: {{ postgres.user }}
- group: {{ postgres.group }}
- makedirs: True
- require:
- cmd: postgresql-cluster-prepared
{%- if postgres.postgresconf %}
postgresql-conf:
file.blockreplace:
- name: {{ postgres.conf_dir }}/postgresql.conf
- marker_start: "# Managed by SaltStack: listen_addresses: please do not edit"
- marker_end: "# Managed by SaltStack: end of salt managed zone --"
- content: |
{{ postgres.postgresconf|indent(8) }}
- show_changes: True
- append_if_not_found: True
- backup: {{ postgres.postgresconf_backup }}
- watch_in:
- service: postgresql-running
- require:
- file: postgresql-config-dir
{%- endif %}
postgresql-pg_hba:
file.managed:
- name: {{ postgres.conf_dir }}/pg_hba.conf
- source: {{ postgres['pg_hba.conf'] }}
- template: jinja
- user: {{ postgres.user }}
- group: {{ postgres.group }}
- mode: 600
- require:
- file: postgresql-config-dir
postgresql-running:
service.running:
- name: {{ postgres.service }}
- enable: True
- reload: True
- watch:
- file: postgresql-pg_hba
postgresql-extra-pkgs-installed:
pkg.installed:
- pkgs: {{ postgres.pkgs_extra }}
### User states
{%- for name, user in postgres.users|dictsort() %}
{{ format_state(name, 'postgres_user', user) }}
- require:
- service: postgresql-running
{%- if 'db_user' in user %}
- postgres_user: postgres_user-{{ user.db_user }}
{%- endif %}
{%- endfor %}
### Tablespace states
{%- for name, tblspace in postgres.tablespaces|dictsort() %}
postgres_tablespace-dir-{{ tblspace.directory}}:
file.directory:
- name: {{ tblspace.directory }}
- user: {{ postgres.user }}
- group: {{ postgres.group }}
- mode: 700
- makedirs: True
- recurse:
- user
- group
{{ format_state(name, 'postgres_tablespace', tblspace) }}
- require:
- file: postgres_tablespace-dir-{{ tblspace.directory }}
{%- if 'owner' in tblspace %}
- postgres_user: postgres_user-{{ tblspace.owner }}
{%- endif %}
- service: postgresql-running
{%- endfor %}
### Database states
{%- for name, db in postgres.databases|dictsort() %}
{{ format_state(name, 'postgres_database', db) }}
- require:
- service: postgresql-running
{%- if 'db_user' in db %}
- postgres_user: postgres_user-{{ db.db_user }}
{%- endif %}
{%- if 'owner' in db %}
- postgres_user: postgres_user-{{ db.owner }}
{%- endif %}
{%- if 'tablespace' in db %}
- postgres_tablespace: postgres_tablespace-{{ db.tablespace }}
{%- endif %}
{%- endfor %}
### Schema states
{%- for name, schema in postgres.schemas|dictsort() %}
{{ format_state(name, 'postgres_schema', schema) }}
- require:
- service: postgresql-running
{%- if 'db_user' in schema %}
- postgres_user: postgres_user-{{ schema.db_user }}
{%- endif %}
{%- if 'dbname' in schema %}
- postgres_database: postgres_database-{{ schema.dbname }}
{%- endif %}
{%- if 'owner' in schema %}
- postgres_user: postgres_user-{{ schema.owner }}
{%- endif %}
{%- endfor %}
### Extension states
{%- for name, extension in postgres.extensions|dictsort() %}
{{ format_state(name, 'postgres_extension', extension) }}
- require:
- service: postgresql-running
- pkg: postgresql-extra-pkgs-installed
{%- if 'db_user' in extension %}
- postgres_user: postgres_user-{{ extension.db_user }}
{%- endif %}
{%- if 'maintenance_db' in extension %}
- postgres_database: postgres_database-{{ extension.maintenance_db }}
{%- endif %}
{%- if 'schema' in extension %}
- postgres_schema: postgres_schema-{{ extension.schema }}
{%- endif %}
{%- endfor %}
{% if grains.os == 'MacOS' %}
- postgres.macos
{% else %}
- postgres.server
- postgres.client
- postgres.manage
{% endif %}

10
postgres/macos/init.sls Normal file
View file

@ -0,0 +1,10 @@
{% from "postgres/map.jinja" import postgres with context %}
include:
{% if postgres.use_upstream_repo == 'postgresapp' %}
- postgres.macos.postgresapp
{% elif postgres.use_upstream_repo == 'homebrew' %}
- postgres.server
- postgres.client
{% endif %}
- postgres.dev

View file

@ -0,0 +1,64 @@
{% from "postgres/map.jinja" import postgres as pg with context %}
# Cleanup first
pg-remove-prev-archive:
file.absent:
- name: '{{ pg.macos.tmpdir }}/{{ pg.macos.archive }}'
- require_in:
- pg-extract-dirs
pg-extract-dirs:
file.directory:
- names:
- '{{ pg.macos.tmpdir }}'
- makedirs: True
- clean: True
- require_in:
- pg-download-archive
pg-download-archive:
pkg.installed:
- name: curl
cmd.run:
- name: curl {{ pg.macos.dl.opts }} -o '{{ pg.macos.tmpdir }}/{{ pg.macos.archive }}' {{ pg.macos.postgresapp.url }}
{% if grains['saltversioninfo'] >= [2017, 7, 0] %}
- retry:
attempts: {{ pg.macos.dl.retries }}
interval: {{ pg.macos.dl.interval }}
{% endif %}
{%- if pg.macos.postgresapp.sum %}
pg-check-archive-hash:
module.run:
- name: file.check_hash
- path: '{{ pg.macos.tmpdir }}/{{ pg.macos.archive }}'
- file_hash: {{ pg.macos.postgresapp.sum }}
- onchanges:
- cmd: pg-download-archive
- require_in:
- archive: pg-package-install
{%- endif %}
pg-package-install:
macpackage.installed:
- name: '{{ pg.macos.tmpdir }}/{{ pg.macos.archive }}'
- store: True
- dmg: True
- app: True
- force: True
- allow_untrusted: True
- onchanges:
- cmd: pg-download-archive
- require_in:
- file: pg-package-install
- file: pg-remove-archive
file.append:
- name: {{ pg.userhomes }}/{{ pg.user }}/.bash_profile
- text: 'export PATH=$PATH:/Applications/Postgres.app/Contents/Versions/latest/bin'
pg-remove-archive:
file.absent:
- name: '{{ pg.macos.tmpdir }}'
- onchanges:
- macpackage: pg-package-install

View file

@ -23,6 +23,8 @@
{{ state }}-{{ name }}:
{{ state }}.{{ ensure|default('present') }}:
{{- format_kwargs(kwarg) }}
- onchanges:
- test: postgres-reload-modules
{%- endmacro %}

88
postgres/manage.sls Normal file
View file

@ -0,0 +1,88 @@
{%- from "postgres/map.jinja" import postgres with context -%}
{%- from "postgres/macros.jinja" import format_state with context -%}
{%- if salt['postgres.user_create']|default(none) is not callable %}
# Salt states for managing PostgreSQL is not available,
# need to provision client binaries first
include:
- postgres.client
{%- if 'server_bins' in postgres and grains['saltversion'] == '2016.11.0' %}
# FIXME: Salt v2016.11.0 bug https://github.com/saltstack/salt/issues/37935
- postgres.server
{%- endif %}
{%- endif %}
# Ensure that Salt is able to use postgres modules
postgres-reload-modules:
test.succeed_with_changes:
- reload_modules: True
# User states
{%- for name, user in postgres.users|dictsort() %}
{{ format_state(name, 'postgres_user', user) }}
{%- endfor %}
# Tablespace states
{%- for name, tblspace in postgres.tablespaces|dictsort() %}
{{ format_state(name, 'postgres_tablespace', tblspace) }}
{%- if 'owner' in tblspace %}
- require:
- postgres_user: postgres_user-{{ tblspace.owner }}
{%- endif %}
{%- endfor %}
# Database states
{%- for name, db in postgres.databases|dictsort() %}
{{ format_state(name, 'postgres_database', db) }}
{%- if 'owner' in db or 'tablespace' in db %}
- require:
{%- endif %}
{%- if 'owner' in db %}
- postgres_user: postgres_user-{{ db.owner }}
{%- endif %}
{%- if 'tablespace' in db %}
- postgres_tablespace: postgres_tablespace-{{ db.tablespace }}
{%- endif %}
{%- endfor %}
# Schema states
{%- for name, schema in postgres.schemas|dictsort() %}
{{ format_state(name, 'postgres_schema', schema) }}
{%- if 'owner' in schema %}
- require:
- postgres_user: postgres_user-{{ schema.owner }}
{%- endif %}
{%- endfor %}
# Extension states
{%- for name, extension in postgres.extensions|dictsort() %}
{{ format_state(name, 'postgres_extension', extension) }}
{%- if 'maintenance_db' in extension or 'schema' in extension %}
- require:
{%- endif %}
{%- if 'maintenance_db' in extension %}
- postgres_database: postgres_database-{{ extension.maintenance_db }}
{%- endif %}
{%- if 'schema' in extension %}
- postgres_schema: postgres_schema-{{ extension.schema }}
{%- endif %}
{%- endfor %}

View file

@ -1,7 +1,6 @@
{% import_yaml "postgres/defaults.yaml" as defaults %}
{% import_yaml "postgres/osmap.yaml" as osmap %}
{% import_yaml "postgres/codenamemap.yaml" as oscodenamemap %}
{% import_yaml "postgres/osmajorreleasemap.yaml" as osmajorreleasemap %}
{% set postgres = salt['grains.filter_by'](
defaults,
@ -11,11 +10,7 @@
merge=salt['grains.filter_by'](
oscodenamemap,
grain='oscodename',
merge=salt['grains.filter_by'](
osmajorreleasemap,
grain='osmajorrelease',
merge=salt['pillar.get']('postgres', {}),
),
merge=salt['pillar.get']('postgres', {}),
),
),
base='postgres',

View file

@ -1,67 +0,0 @@
{% import_yaml "postgres/repo.yaml" as repo %}
{% if grains['os_family'] == 'RedHat' %}
### RedHat releases
{% if repo.use_upstream_repo %}
{% set data_dir = '/var/lib/pgsql/' ~ repo.version ~ '/data' %}
# PostgreSQL from upstream repository
default:
prepare_cluster:
user: postgres
command: /usr/pgsql-{{ repo.version }}/bin/initdb -D {{ data_dir }}
test: test -f {{ data_dir }}/PG_VERSION
env: {}
'6':
prepare_cluster:
user: root
command: service postgresql-{{ repo.version }} initdb
test: test -f {{ data_dir }}/PG_VERSION
env: {}
'7':
prepare_cluster:
user: root
command: /usr/pgsql-{{ repo.version }}/bin/postgresql95-setup initdb
test: test -f {{ data_dir }}/PG_VERSION
env: {}
{% else %}
{% set data_dir = '/var/lib/pgsql/data' %}
# PostgreSQL from OS repositories
default:
prepare_cluster:
user: postgres
command: initdb -D {{ data_dir }}
test: test -f {{ data_dir }}/PG_VERSION
env: {}
'6':
prepare_cluster:
user: root
command: service postgresql initdb
test: test -f {{ data_dir }}/PG_VERSION
env: {}
'7':
prepare_cluster:
user: root
command: postgresql-setup initdb
test: test -f {{ data_dir }}/PG_VERSION
env: {}
{% endif %}
{% else %}
### Empty YAML, no settings for other OS
{}
{% endif %}
# vim: ft=sls

View file

@ -5,11 +5,9 @@
Arch:
conf_dir: /var/lib/postgres/data
prepare_cluster:
user: postgres
command: initdb -D /var/lib/postgresql/data
command: initdb -D /var/lib/postgres/data
test: test -f /var/lib/postgres/data/PG_VERSION
env: {}
pkg_client: postgresql
pkg_client: postgresql-libs
pkg_dev: postgresql
Debian:
@ -19,7 +17,6 @@ Debian:
file: /etc/apt/sources.list.d/pgdg.list
pkg_repo_keyid: ACCC4CF8
pkg_dev: postgresql-server-dev-all
pkg_libpq_dev: libpq-dev
FreeBSD:
user: pgsql
@ -44,18 +41,143 @@ RedHat:
pkg: postgresql{{ release }}-server
pkg_client: postgresql{{ release }}
pkg_libs: postgresql{{ release }}-libs
pkg_dev: postgresql{{ release }}-devel
conf_dir: /var/lib/pgsql/{{ repo.version }}/data
service: postgresql-{{ repo.version }}
prepare_cluster:
command: initdb --pgdata='{{ data_dir }}'
test: test -f '{{ data_dir }}/PG_VERSION'
# Alternatives system
linux:
altpriority: 30
# directory containing PostgreSQL client executables
bin_dir: /usr/pgsql-{{ repo.version }}/bin
client_bins:
- clusterdb
- createdb
- createlang
- createuser
- dropdb
- droplang
- dropuser
- pg_archivecleanup
- pg_basebackup
- pg_config
- pg_dump
- pg_dumpall
- pg_isready
- pg_receivexlog
- pg_restore
- pg_rewind
- pg_test_fsync
- pg_test_timing
- pg_upgrade
- pg_xlogdump
- pgbench
- psql
- reindexdb
- vacuumdb
server_bins:
- initdb
- pg_controldata
- pg_ctl
- pg_resetxlog
- postgres
- postgresql{{ release }}-check-db-dir
- postgresql{{ release }}-setup
- postmaster
{% else %}
pkg: postgresql-server
pkg_client: postgresql
{% endif %}
pkg_libpq_dev: libpqxx-devel
Suse:
pkg_repo:
name: pgdg-sles-{{ release }}
humanname: PostgreSQL {{ repo.version }} $releasever - $basearch
#Using sles-12 upstream repo for opensuse
baseurl: 'https://download.postgresql.org/pub/repos/zypp/{{ repo.version }}/suse/sles-12-$basearch'
key_url: 'https://download.postgresql.org/pub/repos/zypp/{{ repo.version }}/suse/sles-12-$basearch/repodata/repomd.xml.key'
gpgcheck: 1
gpgautoimport: True
{% if repo.use_upstream_repo == true %}
{% set lib_dir = '/var/lib/pgsql/' ~ repo.version ~ '/data' %}
pkg: postgresql{{ release }}-server
pkg_client: postgresql{{ release }}
pkg_dev: postgresql{{ release }}-devel
pkg_libs: postgresql{{ release }}-libs
conf_dir: {{ lib_dir }}
service: postgresql-{{ repo.version }}
prepare_cluster:
command: /usr/pgsql-{{ repo.version }}/bin/initdb --pgdata='{{ lib_dir }}'
test: test -f '{{ lib_dir }}/PG_VERSION'
# Alternatives system
linux:
altpriority: 30
# directory containing PostgreSQL client executables
bin_dir: /usr/pgsql-{{ repo.version }}/bin
client_bins:
- pg_archivecleanup
- pg_config
- pg_isready
- pg_receivexlog
- pg_rewind
- pg_test_fsync
- pg_test_timing
- pg_upgrade
- pg_xlogdump
- pgbench
server_bins:
- initdb
- pg_controldata
- pg_ctl
- pg_resetxlog
- postgres
- postgresql{{ release }}-check-db-dir
- postgresql{{ release }}-setup
- postmaster
{% else %}
pkg: postgresql-server
pkg_client: postgresql
{% endif %}
pkg_libpq_dev: libqpxx
{%- if grains.os == 'MacOS' %}
## jinja check avoids rendering noise/failure on Linux
MacOS:
{%- if repo.use_upstream_repo == 'homebrew' %}
service: homebrew.mxcl.postgresql
{%- elif repo.use_upstream_repo == 'postgresapp' %}
service: com.postgresapp.Postgres2
{%- endif %}
pkg: postgresql
pkg_client:
pkg_libpq_dev:
userhomes: /Users
user: {{ repo.user }}
group: {{ repo.group }}
conf_dir: /Users/{{ repo.user }}/Library/AppSupport/postgres_{{ repo.use_upstream_repo }}
prepare_cluster:
command: initdb -D /Users/{{ repo.user }}/Library/AppSupport/postgres_{{ repo.use_upstream_repo }}
test: test -f /Users/{{ repo.user }}/Library/AppSupport/postgres_{{ repo.use_upstream_repo }}/PG_VERSION
user: {{ repo.user }}
group: {{ repo.group }}
{%- endif %}
# vim: ft=sls

View file

@ -2,4 +2,4 @@
postgresql-python:
pkg.installed:
- name: {{ postgres.python}}
- name: {{ postgres.pkg_python}}

View file

@ -8,4 +8,12 @@ use_upstream_repo: {{ salt['pillar.get']('postgres:use_upstream_repo',
version: {{ salt['pillar.get']('postgres:version',
defaults.postgres.version) }}
#Early lookup for system user on MacOS
{% if grains.os == 'MacOS' %}
{% set sysuser = salt['pillar.get']('postgres.user') or salt['cmd.run']("stat -f '%Su' /dev/console") %}
{% set sysgroup = salt['pillar.get']('postgres.group') or salt['cmd.run']("stat -f '%Sg' /dev/console") %}
user: {{ sysuser }}
group: {{ sysgroup }}
{% endif %}
# vim: ft=sls

45
postgres/server/image.sls Normal file
View file

@ -0,0 +1,45 @@
{%- from "postgres/map.jinja" import postgres with context -%}
# This state is used to launch PostgreSQL with ``pg_ctl`` command and enable it
# on "boot" during an image (Docker, Virtual Appliance, AMI) preparation
{%- if postgres.bake_image %}
include:
- postgres.server
# An attempt to start PostgreSQL with `pg_ctl`
postgresql-start:
cmd.run:
- name: pg_ctl -D {{ postgres.conf_dir }} -l logfile start
- runas: {{ postgres.user }}
- unless:
- ps -p $(head -n 1 {{ postgres.conf_dir }}/postmaster.pid) 2>/dev/null
- require:
- file: postgresql-pg_hba
# Try to enable PostgreSQL in "manual" way
postgresql-enable:
cmd.run:
{%- if salt['file.file_exists']('/bin/systemctl') %}
- name: systemctl enable {{ postgres.service }}
{%- elif salt['cmd.which']('chkconfig') %}
- name: chkconfig {{ postgres.service }} on
{%- elif salt['file.file_exists']('/usr/sbin/update-rc.d') %}
- name: update-rc.d {{ service }} defaults
{%- else %}
# Nothing to do
- name: 'true'
{%- endif %}
- require:
- cmd: postgresql-start
{%- else %}
postgresql-start:
test.show_notification:
- text: The 'postgres:bake_image' Pillar is disabled (set to 'False').
{%- endif %}

190
postgres/server/init.sls Normal file
View file

@ -0,0 +1,190 @@
{%- from "postgres/map.jinja" import postgres with context %}
{%- set includes = [] %}
{%- if postgres.bake_image %}
{%- do includes.append('postgres.server.image') %}
{%- endif %}
{%- if postgres.use_upstream_repo == true -%}
{%- do includes.append('postgres.upstream') %}
{%- endif %}
{%- if includes -%}
include:
{{ includes|yaml(false)|indent(2) }}
{%- endif %}
{%- set pkgs = [postgres.pkg] + postgres.pkgs_extra %}
# Install, configure and start PostgreSQL server
postgresql-server:
pkg.installed:
- pkgs: {{ pkgs }}
{%- if postgres.use_upstream_repo == true %}
- refresh: True
- require:
- pkgrepo: postgresql-repo
{%- endif %}
{%- if grains.os == 'MacOS' %}
#Register as Launchd LaunchAgent for system users
- require_in:
- file: postgresql-server
file.managed:
- name: /Library/LaunchAgents/{{ postgres.service }}.plist
- source: /usr/local/opt/postgres/{{ postgres.service }}.plist
- group: wheel
- require_in:
- service: postgresql-running
{%- else %}
# Alternatives system. Make server binaries available in $PATH
{%- if 'bin_dir' in postgres and postgres.linux.altpriority %}
{%- for bin in postgres.server_bins %}
{%- set path = salt['file.join'](postgres.bin_dir, bin) %}
{{ bin }}:
alternatives.install:
- link: {{ salt['file.join']('/usr/bin', bin) }}
- path: {{ path }}
- priority: {{ postgres.linux.altpriority }}
- onlyif: test -f {{ path }}
- require:
- pkg: postgresql-server
- require_in:
- cmd: postgresql-cluster-prepared
{%- endfor %}
{%- endif %}
{%- endif %}
postgresql-cluster-prepared:
cmd.run:
- name: {{ postgres.prepare_cluster.command }}
- cwd: /
- runas: {{ postgres.prepare_cluster.user }}
- env: {{ postgres.prepare_cluster.env }}
- unless:
- {{ postgres.prepare_cluster.test }}
- require:
- pkg: postgresql-server
postgresql-config-dir:
file.directory:
- name: {{ postgres.conf_dir }}
- user: {{ postgres.user }}
- group: {{ postgres.group }}
- dir_mode: 775
- force: True
- file_mode: 644
- recurse:
- user
- group
- makedirs: True
- require:
- cmd: postgresql-cluster-prepared
{%- if postgres.postgresconf %}
postgresql-conf:
file.blockreplace:
- name: {{ postgres.conf_dir }}/postgresql.conf
- marker_start: "# Managed by SaltStack: listen_addresses: please do not edit"
- marker_end: "# Managed by SaltStack: end of salt managed zone --"
- content: |
{{ postgres.postgresconf|indent(8) }}
- show_changes: True
- append_if_not_found: True
{#- Detect empty values (none, '') in the config_backup #}
- backup: {{ postgres.config_backup|default(false, true) }}
- require:
- file: postgresql-config-dir
- watch_in:
- service: postgresql-running
{%- endif %}
{%- set pg_hba_path = salt['file.join'](postgres.conf_dir, 'pg_hba.conf') %}
postgresql-pg_hba:
file.managed:
- name: {{ pg_hba_path }}
- user: {{ postgres.user }}
- group: {{ postgres.group }}
- mode: 600
{%- if postgres.acls %}
- source: {{ postgres['pg_hba.conf'] }}
- template: jinja
- defaults:
acls: {{ postgres.acls }}
{%- if postgres.config_backup %}
# Create the empty file before managing to overcome the limitation of check_cmd
- onlyif: test -f {{ pg_hba_path }} || touch {{ pg_hba_path }}
# Make a local backup before the file modification
- check_cmd: >-
salt-call --local file.copy
{{ pg_hba_path }} {{ pg_hba_path ~ postgres.config_backup }} remove_existing=true
{%- endif %}
{%- else %}
- replace: False
{%- endif %}
- require:
- file: postgresql-config-dir
{%- set pg_ident_path = salt['file.join'](postgres.conf_dir, 'pg_ident.conf') %}
postgresql-pg_ident:
file.managed:
- name: {{ pg_ident_path }}
- user: {{ postgres.user }}
- group: {{ postgres.group }}
- mode: 600
{%- if postgres.identity_map %}
- source: {{ postgres['pg_ident.conf'] }}
- template: jinja
- defaults:
mappings: {{ postgres.identity_map }}
{%- if postgres.config_backup %}
# Create the empty file before managing to overcome the limitation of check_cmd
- onlyif: test -f {{ pg_ident_path }} || touch {{ pg_ident_path }}
# Make a local backup before the file modification
- check_cmd: >-
salt-call --local file.copy
{{ pg_ident_path }} {{ pg_ident_path ~ postgres.config_backup }} remove_existing=true
{%- endif %}
{%- else %}
- replace: False
{%- endif %}
- require:
- file: postgresql-config-dir
{%- for name, tblspace in postgres.tablespaces|dictsort() %}
postgresql-tablespace-dir-{{ name }}:
file.directory:
- name: {{ tblspace.directory }}
- user: {{ postgres.user }}
- group: {{ postgres.group }}
- mode: 700
- makedirs: True
- recurse:
- user
- group
- require:
- pkg: postgresql-server
{%- endfor %}
{%- if not postgres.bake_image %}
# Start PostgreSQL server using OS init
postgresql-running:
service.running:
- name: {{ postgres.service }}
- enable: True
{% if grains.os not in ('MacOS',) %}
- reload: True
{% endif %}
- watch:
- file: postgresql-pg_hba
- file: postgresql-pg_ident
{%- endif %}

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>limit.maxfiles</string>
<key>ProgramArguments</key>
<array>
<string>/bin/launchctl</string>
<string>limit</string>
<string>maxfiles</string>
<string>{{ soft_limit }}</string>
<string>{{ hard_limit }}</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>ServiceIPC</key>
<false/>
</dict>
</plist>

View file

@ -0,0 +1,8 @@
#!/usr/bin/env bash
shortcutName='${1}'
app="postgres.app"
Source="/Applications/$app"
Destination="{{ homes }}/{{ user }}/Desktop/${shortcutName}"
/usr/bin/osascript -e "tell application \"Finder\" to make alias file to POSIX file \"$Source\" at POSIX file \"$Destination\""

View file

@ -1,5 +1,3 @@
{%- from "postgres/map.jinja" import postgres with context -%}
######################################################################
# ATTENTION! Managed by SaltStack. #
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN! #
@ -22,7 +20,7 @@ local all postgres peer
# TYPE DATABASE USER ADDRESS METHOD
{%- for acl in postgres.acls %}
{%- for acl in acls %}
{%- if acl|first() == 'local' %}
{%- if acl|length() == 3 %}
@ -38,5 +36,5 @@ local all postgres peer
{%- endif %}
{%- endif %}
{{ '{0:<8}{1:<16}{2:<16}{3:<24}{4}'.format(*acl) -}}
{{ '{0:<7} {1:<15} {2:<15} {3:<23} {4}'.format(*acl) -}}
{% endfor %}

View file

@ -0,0 +1,51 @@
######################################################################
# ATTENTION! Managed by SaltStack. #
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN! #
######################################################################
#
# 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 mappings %}
{{ '{0:<15} {1:<22} {2}'.format(mapping) -}}
{% endfor %}

View file

@ -3,17 +3,17 @@
{%- if 'pkg_repo' in postgres -%}
{%- if postgres.use_upstream_repo -%}
{%- if postgres.use_upstream_repo == true -%}
# Add upstream repository for your distro
install-postgresql-repo:
postgresql-repo:
pkgrepo.managed:
{{- format_kwargs(postgres.pkg_repo) }}
{%- else -%}
# Remove the repo configuration (and GnuPG key) as requested
remove-postgresql-repo:
postgresql-repo:
pkgrepo.absent:
- name: {{ postgres.pkg_repo.name }}
{%- if 'pkg_repo_keyid' in postgres %}
@ -25,9 +25,11 @@ remove-postgresql-repo:
{%- else -%}
# Notify that we don't manage this distro
install-postgresql-repo:
{% if grains.os not in ('Windows', 'MacOS',) %}
postgresql-repo:
test.show_notification:
- text: |
PostgreSQL does not provide package repository for {{ grains['osfinger'] }}
{% endif %}
{%- endif %}