diff --git a/pillar.example b/pillar.example index 43ffac9..82c357d 100644 --- a/pillar.example +++ b/pillar.example @@ -31,11 +31,39 @@ postgres: # METHOD could be omitted, 'md5' will be appended by default. acls: - ['local', 'db1', 'localUser'] - - ['host', 'db2', 'remoteUser', '123.123.0.0/24'] + - ['host', 'db2', 'remoteUser', '192.168.33.0/24'] # PostgreSQL service name service: postgresql + # 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. + # + # Format is the following: + # + #: + # NAME: + # ensure: # 'present' is the default + # ARGUMENT: VALUE + # ... + # + # where 'NAME' is the state name, 'ARGUMENT' is the kwarg name, and + # 'VALUE' is kwarg value. + # + # For example, the Pillar: + # + #users: + # testUser: + # password: test + # + # will render such state: + # + #postgres_user-testUser: + # postgres_user.present: + # - name: testUser + # - password: test users: localUser: ensure: present @@ -57,12 +85,6 @@ postgres: absentUser: ensure: absent - password: '98ruj923h4rf' - createdb: False - createroles: False - createuser: False - inherit: True - replication: False tablespaces: my_space: @@ -75,26 +97,27 @@ postgres: template: 'template0' lc_ctype: 'en_US.UTF-8' lc_collate: 'en_US.UTF-8' - # optional schemas to enable on database - schemas: - uuid_ossp: - owner: localUser - # optional extensions to enable on database - extensions: - uuid-ossp: - schema: uuid_ossp db2: - owner: 'localUser' - user: 'remoteUser' + owner: 'remoteUser' template: 'template0' lc_ctype: 'en_US.UTF-8' lc_collate: 'en_US.UTF-8' tablespace: 'my_space' - # optional extensions to enable on database - # extensions: - # postgis: - # backup extension defaults to .bak if postgresconf_backup is True. + # optional schemas to enable on database + schemas: + uuid_ossp: + dbname: db1 + owner: localUser + + # optional extensions to install in schema + extensions: + uuid-ossp: + schema: uuid_ossp + 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. diff --git a/postgres/codenamemap.yaml b/postgres/codenamemap.yaml index fe05087..06ed39d 100644 --- a/postgres/codenamemap.yaml +++ b/postgres/codenamemap.yaml @@ -1,8 +1,8 @@ {% macro ubuntu_block(name, version) %} -{% if salt['pillar.get']('postgres:use_upstream_repo', False) %} - {% set version = salt['pillar.get']('postgres:version', '9.5') %} -{% endif %} + {% if salt['pillar.get']('postgres:use_upstream_repo', False) %} + {% set version = salt['pillar.get']('postgres:version', '9.5') %} + {% endif %} {{ name }}: pkg_repo: deb http://apt.postgresql.org/pub/repos/apt/ {{ name }}-pgdg main diff --git a/postgres/defaults.yaml b/postgres/defaults.yaml index 16cf50b..4b95b7b 100644 --- a/postgres/defaults.yaml +++ b/postgres/defaults.yaml @@ -19,8 +19,10 @@ postgres: - ['host', 'all', 'all', '::1/128', 'md5'] service: postgresql users: {} - databases: {} tablespaces: {} + databases: {} + schemas: {} + extensions: {} postgresconf_backup: True postgresconf: "" diff --git a/postgres/init.sls b/postgres/init.sls index accb3a6..75f3caf 100644 --- a/postgres/init.sls +++ b/postgres/init.sls @@ -1,6 +1,7 @@ # -*- mode: yaml -*- {%- from "postgres/map.jinja" import postgres with context -%} +{%- from "postgres/macros.jinja" import format_state with context -%} {%- if postgres.use_upstream_repo %} @@ -9,6 +10,8 @@ include: {%- endif %} +### Installation states + postgresql-installed: pkg.installed: - name: {{ postgres.pkg }} @@ -77,195 +80,98 @@ postgresql-extra-pkgs-installed: pkg.installed: - pkgs: {{ postgres.pkgs_extra }} -{% for name, user in postgres.users.items() %} -postgresql-user-{{ name }}: -{% if user.get('ensure', 'present') == 'absent' %} - postgres_user.absent: - - name: {{ name }} - - user: {{ user.get('runas', postgres.user) }} -{% if user.get('user') %} - - db_user: {{ user.user }} -{% endif %} -{% else %} - postgres_user.present: - - name: {{ name }} - - createdb: {{ user.get('createdb', False) }} - - createroles: {{ user.get('createroles', False) }} - - createuser: {{ user.get('createuser', False) }} - - inherit: {{ user.get('inherit', True) }} - - replication: {{ user.get('replication', False) }} - - password: {{ user.password }} - - superuser: {{ user.get('superuser', False) }} - - user: {{ user.get('runas', postgres.user) }} -{% if user.get('user') %} - - db_user: {{ user.get('runas', postgres.user) }} -{% endif %} -{% endif %} +### User states + +{%- for name, user in postgres.users|dictsort() %} + +{{ format_state(name, 'postgres_user', user) }} - require: - service: postgresql-running -{% if user.get('user') %} - - postgres_user: postgresql-user-{{ user.user }} -{% endif %} -{% endfor %} + {%- if 'db_user' in user %} + - postgres_user: postgres_user-{{ user.db_user }} + {%- endif %} -{% for name, tblspace in postgres.tablespaces.items() %} -postgresql-tablespace-dir-perms-{{ tblspace.directory}}: +{%- 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 -postgresql-tablespace-{{ name }}: - postgres_tablespace.present: - - name: {{ name }} - - directory: {{ tblspace.directory }} - - user: {{ tblspace.get('runas', postgres.user) }} -{% if tblspace.get('db_user') %} - - db_user: {{ tblspace.db_user }} -{% endif %} -{% if tblspace.get('db_password') %} - - db_password: {{ tblspace.db_password }} -{% endif %} -{% if tblspace.get('db_host') %} - - db_host: {{ tblspace.db_host }} -{% endif %} -{% if tblspace.get('db_port') %} - - db_port: {{ tblspace.db_port }} -{% endif %} -{% if tblspace.get('owner') %} - - owner: {{ tblspace.owner }} -{% endif %} +{{ 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 - - file: postgresql-tablespace-dir-perms-{{ tblspace.directory}} -{% endfor %} -{% for name, db in postgres.databases.items() %} -postgresql-db-{{ name }}: -{% if db.get('ensure', 'present') == 'absent' %} - postgres_database.absent: - - name: {{ name }} - - user: {{ db.get('runas', postgres.user) }} -{% if db.get('user') %} - - db_user: {{ db.user }} -{% endif %} - - require: - - service: postgresql-running -{% else %} - postgres_database.present: - - name: {{ name }} - {% if 'encoding' in db %} - - encoding: {{ db.encoding }} - {% endif %} - {% if 'lc_ctype' in db %} - - lc_ctype: {{ db.lc_ctype }} - {% endif %} - {% if 'lc_collate' in db %} - - lc_collate: {{ db.lc_collate }} - {% endif %} - - template: {{ db.get('template', 'template0') }} - - tablespace: {{ db.get('tablespace', 'pg_default') }} - {% if db.get('owner') %} - - owner: {{ db.owner }} - {% endif %} - - user: {{ db.get('runas', postgres.user) }} - {% if db.get('db_user') %} - - db_user: {{ db.db_user }} - {% endif %} - {% if db.get('db_password') %} - - db_password: {{ db.db_password }} - {% endif %} - {% if db.get('db_host') %} - - db_host: {{ db.db_host }} - {% endif %} - {% if db.get('db_port') %} - - db_port: {{ db.db_port }} - {% endif %} - - require: - - service: postgresql-running - {% if db.get('user') %} - - postgres_user: postgresql-user-{{ db.user }} - {% endif %} - {% if db.get('owner') %} - - postgres_user: postgresql-user-{{ db.owner }} - {% endif %} - {% if db.get('tablespace') %} - - postgres_tablespace: postgresql-tablespace-{{ db.get('tablespace') }} - {% endif %} +{%- endfor %} -{# NOTE: postgres_schema doesn't have a 'runas' equiv. at all #} -{% for schema_name, schema in db.get('schemas', dict()).items() %} -postgresql-schema-{{ schema_name }}-for-db-{{ name }}: -{% if schema.get('ensure', 'present') == 'absent' %} - postgres_schema.absent: - - name: {{ schema_name }} - {% if schema.get('user') %} - - db_user: {{ schema.user }} - {% endif %} - - require: - - service: postgresql-running -{% else %} - postgres_schema.present: - - name: {{ schema_name }} - - dbname: {{ name }} - {% if schema.get('user') %} - - db_user: {{ schema.user }} - {% endif %} -{% if schema.get('owner') %} - - owner: {{ schema.owner }} -{% endif %} - - require: - - service: postgresql-running - - postgres_database: postgresql-db-{{ name }} - {% if schema.get('user') %} - - postgres_user: postgresql-user-{{ schema.user }} - {% endif %} - {% if schema.get('owner') %} - - postgres_user: postgresql-user-{{ schema.owner }} - {% endif %} -{% endif %} -{% endfor %} +### Database states -{% for ext_name, ext in db.get('extensions', dict()).items() %} -postgresql-ext-{{ ext_name }}-for-db-{{ name }}: - {% if ext.get('ensure', 'present') == 'absent' %} - postgres_extension.absent: - - name: {{ ext_name }} - - user: {{ ext.get('runas', postgres.user) }} - {% if ext.get('user') %} - - db_user: {{ ext.user }} - {% endif %} - - require: - - service: postgresql-running - {% else %} - postgres_extension.present: - - name: {{ ext_name }} - - user: {{ ext.get('runas', postgres.user) }} - {% if ext.get('user') %} - - db_user: {{ ext.user }} - {% endif %} - {% if ext.get('version') %} - - ext_version: {{ ext.version }} - {% endif %} - {% if ext.get('schema') %} - - schema: {{ ext.schema }} - {% endif %} - - maintenance_db: {{ name }} - - require: - - service: postgresql-running - - postgres_database: postgresql-db-{{ name }} - {% if ext.get('user') %} - - postgres_user: postgresql-user-{{ ext.user }} - {% endif %} - {% if ext.get('schema') %} - - postgres_schema: postgresql-schema-{{ ext.schema }}-for-db-{{ name }} - {% endif %} - {% endif %} -{% endfor %} +{%- for name, db in postgres.databases|dictsort() %} -{% endif %} -{% endfor %} +{{ 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 %} diff --git a/postgres/macros.jinja b/postgres/macros.jinja new file mode 100644 index 0000000..d30bb9b --- /dev/null +++ b/postgres/macros.jinja @@ -0,0 +1,21 @@ +{%- from "postgres/map.jinja" import postgres with context -%} + +{%- macro format_state(name, state, kwarg) %} + + {%- do kwarg.update({'name': name}) %} + {%- if 'ensure' in kwarg %} + {%- set ensure = kwarg.pop('ensure') %} + {%- endif %} + {%- if 'user' not in kwarg and state != 'postgres_schema' %} + {%- do kwarg.update({'user': postgres.user}) %} + {%- endif -%} + +{{ state }}-{{ name }}: + {{ state }}.{{ ensure|default('present') }}: + {%- for k, v in kwarg|dictsort() %} + - {{ k }}: {{ v }} + {%- endfor %} + +{%- endmacro %} + +# vim: ft=sls diff --git a/test/integration/default/serverspec/postgres_spec.rb b/test/integration/default/serverspec/postgres_spec.rb index f709f58..768e62f 100644 --- a/test/integration/default/serverspec/postgres_spec.rb +++ b/test/integration/default/serverspec/postgres_spec.rb @@ -19,5 +19,5 @@ describe file('/srv/my_tablespace') do end describe command(%q{su - postgres -c 'psql -qtc "\l+ db2"'}) do - its(:stdout) { should match(/db2.*localUser.*UTF8.*en_US\.UTF-8.*en_US\.UTF-8.*my_space/) } + its(:stdout) { should match(/db2.*remoteUser.*UTF8.*en_US\.UTF-8.*en_US\.UTF-8.*my_space/) } end