postgresql
Version information
This version is compatible with:
- Puppet Enterprise 2023.8.x, 2023.7.x, 2023.6.x, 2023.5.x, 2023.4.x, 2023.3.x, 2023.2.x, 2023.1.x, 2023.0.x, 2021.7.x, 2021.6.x, 2021.5.x, 2021.4.x, 2021.3.x, 2021.2.x, 2021.1.x, 2021.0.x, 2019.8.x, 2019.7.x, 2019.5.x, 2019.4.x, 2019.3.x, 2019.2.x, 2019.1.x, 2019.0.x, 2018.1.x, 2017.3.x, 2017.2.x, 2017.1.x, 2016.5.x, 2016.4.x
- Puppet >= 3.8.0
- , , , ,
Tasks:
- isreplicapaused
- pausereplica
- resumereplica
Start using this module
Add this module to your Puppetfile:
mod 'eyp-postgresql', '0.5.2'
Learn more about managing modules with a PuppetfileDocumentation
postgresql
Table of Contents
Overview
This module can manage a postgres configured as:
- standalone
- streaming replication (master or slave)
Module Description
Installs and configures PostgreSQL on CentOS 6 and 7
Setup
What postgresql affects
- Installs PostgreSQL:
- configures:
- postgres.conf
- pg_hba
- pg_stat_statements
- backup script using pg_dump
- pgsnapshot tool (tool for backing up and restore the database using LVM snapshots or AWS snapshots)
- cronjob for vacuum_analyze
- it can manage the following DB objects:
- roles
- schemas
- databases
- extensions (postgis and pg_stat_statements can be managed using it's own class in the module)
- if eyp-sysctl is present:
- overcommit_memory = 2 - total virtual address space on the system is limited to (SWAP + RAM ·( /proc/sys/vm/overcommit_ratio /100))
- shmmax: maximum size of shared memory segment (default: ceiling(sprintf('%f', $::memorysize_mb)·786432))
- shmall: total amount of shared memory available (default: ceiling(ceiling(sprintf('%f',$::memorysize_mb)·786432)/$::eyp_postgresql_pagesize))
Setup Requirements
- This module requires optionally eyp/sysctl module installed to be able to manage kernel.shmmax, kernel.shmall and vm.overcommit_memory
- Mountpoints must be already in place (datadir, archive_dir...) and datadir must be empty
- Python module psycopg2 is just required to be able to use tasks
Beginning with postgresql
Install a postgres Using puppet-masterless:
- Make sure git is installed
yum install git
Clone puppet-masterless to /opt and install dependencies:
cd /opt/
git clone https://github.com/jordiprats/puppet-masterless
cd puppet-masterless/
bash setup.sh
Install puppet module and apply demo .pp:
./localpuppetmaster.sh -d /tmp/postgres -r https://github.com/jordiprats/eyp-postgresql
./localpuppetmaster.sh -d /tmp/postgres -s /tmp/postgres/modules/postgresql/examples/demo_pg10.pp
Usage
streaming replication setup
# 192.168.56.29
node 'pgm'
{
class { 'sysctl': }
class { 'postgresql':
wal_level => 'hot_standby',
max_wal_senders => '3',
checkpoint_segments => '8',
wal_keep_segments => '8',
}
postgresql::hba_rule { 'test':
user => 'replicator',
database => 'replication',
address => '192.168.56.0/24',
}
postgresql::role { 'replicator':
replication => true,
password => 'replicatorpassword',
}
postgresql::schema { 'jordi':
owner => 'replicator',
}
}
# 192.168.56.30
node 'pgs'
{
class { 'sysctl': }
class { 'postgresql':
wal_level => 'hot_standby',
max_wal_senders => '3',
checkpoint_segments => '8',
wal_keep_segments => '8' ,
hot_standby => true,
initdb => false,
}
class { 'postgresql::streaming_replication':
masterhost => '192.168.56.29',
masterusername => 'replicator',
masterpassword => 'replicatorpassword',
}
}
backup configurtion
postgresql::pgdumpbackup { "backup logic":
destination => '/backup',
mailto => 'backup_notifications@systemadmin.es',
idhost => 'postgresmaster01',
}
postgresmaster using hiera
---
classes:
- postgresql
- postgresql::pgstatsstatements
postgresql::port: 60901
postgresql::wal_level: hot_standby
postgresql::max_wal_senders: 3
postgresql::checkpoint_segments: 16
postgresql::wal_keep_segments: 8
postgresql::archive_mode: true
postgresql::max_connections: 200
postgresql::archive_mode: true
postgresql::archive_command_custom: 'rsync --exclude lost+found -a %p barman@192.168.52.21:/var/lib/barman/pgm/incoming/%f'
postgresql::shared_preload_libraries:
- pg_stat_statements
postgresroles:
extension:
password: '1234'
port: 60901
extension_ro:
password: '1234'
port: 60901
extension_rw:
password: '1234'
port: 60901
replicator:
port: 60901
password: '1234'
replication: true
postgresschemas:
extension:
owner: extension
port: 60901
postgres slave using hiera
---
classes:
- postgresql
- postgresql::pgstatsstatements
- postgresql::streaming_replication
postgresql::port: 60901
postgresql::wal_level: hot_standby
postgresql::max_wal_senders: 3
postgresql::checkpoint_segments: 16
postgresql::wal_keep_segments: 8
postgresql::archive_mode: true
postgresql::max_connections: 200
postgresql::initdb: false
postgresql::hot_standby: true
postgresql::shared_preload_libraries:
- pg_stat_statements
postgresql::streaming_replication::masterhost: 192.168.52.20
postgresql::streaming_replication::masterport: 60901
postgresql::streaming_replication::masterusername: replicator
postgresql::streaming_replication::masterpassword: af35dbf3394b2b961fea37db2b2bfb0c
hba rules using hiera
---
hbarules:
barman:
user: postgres
database: all
address: '192.168.52.21/32'
auth_method: trust
replicator:
user: replicator
database: replication
address: '192.168.52.0/24'
nagios:
user: nagios
database: nagios
address: '1.2.3.4/32'
nagiospre:
user: nagios
database: nagios
address: '1.2.3.4/32'
extension:
user: extension
database: extension
address: '192.168.52.0/24'
extensionRO:
user: extension_ro
database: extension
address: '192.168.52.0/24'
extensionRW:
user: extension_rw
database: extension
address: '192.168.52.0/24'
change default schema
class { 'postgresql':
wal_level => 'hot_standby',
max_wal_senders => '3',
checkpoint_segments => '8',
wal_keep_segments => '8',
version => '9.6',
search_path => [ 'demoschema' ],
}
pgsnapshot
This section describes pgsnapshot usage as a reference without actually install it via puppet (not recommended) using an empty config file, passing settings via cli options. Please note this is not the intended usage
touch demo.cfg
In the real world a sample config file would look like this:
[pgsnapshot]
snapsize=30G
to=backup.reports@systemadmin.es
host-id=cpe0014535
keeplvmsnaps=0
keepAWSsnapdays=7
aws=true
config file options
All options need to be in the [pgsnapshot] section
- pgusername: Postgre's username (default: postgres)
- to: Send a backup report to this address (default: do not send any report)
- host-id: Force a specific host id (default: server's FQDN)
- lvmdisk: Use a specific LVM disk (default: connect to postgres to get the actual datadir)
- snapsize: Snapshot size - recommended to be large if you plan to keep snapshots and small if you plan to use AWS snapshots (default: 5G)
- keeplvmsnaps: How many LVM snapshots to keep (default: 2)
- snapshotbasename: LVM snapshot basename (default: snap)
- logdir: Where to keep log files for each action (default: /var/log/pgsnapshot)
- aws: Use AWS snapshots (default: false)
- keepAWSsnapdays: Delete AWS snapshots older than N days (default: 7)
- force-ami: Force a specific AMI for the restored instance (default: use the same AMI as the running instance)
These options and the cronjob for pgsnapshot will be configured using postgresql::backup::pgsnapshot
backup - AWS snapshot
Make a AWS snapshot backups and delete AWS snapshots older that 10 days
localpuppetmaster.sh -d /tmp/postgres -r https://github.com/NTTCom-mS/eyp-postgresql; python /tmp/postgres/modules/postgresql/files/pgsnapshot/pgsnapshot.py -c demo.cfg -a -k 10
backup - LVM snapshot
Make a LVM snapshot backups keeping last 10 LVM snapshots
localpuppetmaster.sh -d /tmp/postgres -r https://github.com/NTTCom-mS/eyp-postgresql; python /tmp/postgres/modules/postgresql/files/pgsnapshot/pgsnapshot.py -c demo.cfg -K 10
list backups - AWS snapshots
localpuppetmaster.sh -d /tmp/postgres -r https://github.com/NTTCom-mS/eyp-postgresql; python /tmp/postgres/modules/postgresql/files/pgsnapshot/pgsnapshot.py -c demo.cfg -a -L
Sample output:
* snap.20181207000001
* snap.20181208000001
* snap.20181209000001
* snap.20181210000001
* snap.20181211000001
* snap.20181212000004
* snap.20181213000001
list backups - LVM snapshots
localpuppetmaster.sh -d /tmp/postgres -r https://github.com/NTTCom-mS/eyp-postgresql; python /tmp/postgres/modules/postgresql/files/pgsnapshot/pgsnapshot.py -c demo.cfg -L
Sample output:
* snap.20181207000001
* snap.20181208000001
restore - AWS snapshot
restore AWS snapshot named snap.20181212122000
localpuppetmaster.sh -d /tmp/postgres -r https://github.com/NTTCom-mS/eyp-postgresql; python /tmp/postgres/modules/postgresql/files/pgsnapshot/pgsnapshot.py -c demo.cfg -a -r snap.20181212122000
As output you'll get the instance id and the public DNS name, for example:
i-029aca55f79548fc5: ec2-63-33-65-78.eu-west-1.compute.amazonaws.com
The restored instance will have the same exact HBA rules a original instance
Reference
classes
postgresql
It uses the following (private) classes to install, configure and manage PostgreSQL:
- postgresql::install: Installation and initdb
- postgresql::config: Modifies configuration files
- postgresql::service: Manages postgres service
Options:
- version: version to install (default: 9.2)
- datadir: datadir to use (default: /var/lib/pgsql/9.2/data)
- initdb: boolean, true to create datadir's directies. In a standby server with streaming replication you want to set it to false (default: true)
- manage_service: boolean, true to manage PostgreSQL's service (default: true)
- archive_command_custom: custom archive command
- archive_dir: archive dir, if archive_command_custom is undef, it will be: test ! -f ${archive_dir}/%f && cp %p ${archive_dir}/%f
- archive_dir_user: archive dir user (default: undef)
- archive_dir_group: archive dir group (default: undef)
- archive_dir_mode: archive dir mode (default: undef)
- archive_dir_chmod: chmod to this mask if using archive_dir (default: undef)
- overcommit_memory: modes available:
- undef: do not change it
- 0: heuristic overcommit (this is the default)
- 1: always overcommit, never check
- 2: always check, never overcommit(default: 2)',
- shmmax: maximum size of shared memory segment (default: ceiling(sprintf('%f', $::memorysize_mb)·786432)) you can set it to undef to disable
- shmall: total amount of shared memory available (default: ceiling(ceiling(sprintf('%f',$::memorysize_mb)·786432)/$::eyp_postgresql_pagesize)) you can set it to undef to disable
- for directly mapped variables (lc_messages, listen, port...) check postgres documentation:
- port (default: 5432)
- listen (default: *)
- max_connections (default: 100)
- wal_level (default: hot_standby)
- max_wal_senders (default: 0)
- checkpoint_segments (default: 16)
- wal_keep_segments (default: 0)
- hot_standby
- pidfile
- log_directory
- log_filename
- track_activities
- track_counts
- autovacuum:
- cleanup is triggered whenever the number of dead tuples (which you can see as pg_stat_all_tables.n_dead_tup) exceeds threshold + pg_class.reltuples * scale_facto
- autovacuum_vacuum_scale_factor (default: 0.0)
- autovacuum_vacuum_threshold (default: 5000)
- autovacuum_analyze_scale_factor (default: 0.0)
- autovacuum_analyze_threshold (default: 5000)
- autovacuum_freeze_max_age (default: undef)
- timezone
- log_timezone
- superuser_reserved_connections
- archive_mode
- archive_timeout
- archived_wals_retention
- archived_wals_hour
- archived_wals_minute
- archived_wals_month
- archived_wals_monthday
- archived_wals_weekday
- maintenance_work_mem
- wal_buffers
- work_mem
- shared_buffers (autocalculated to 1/4 main RAM)
- lc_messages (default: C)
- lc_monetary (default: en_US.UTF-8)
- lc_numeric (default: en_US.UTF-8)
- lc_time (default: en_US.UTF-8)
- default_text_search_config (default: pg_catalog.english)
- shared_preload_libraries (default: undef)
usage example:
class { 'postgresql': }
postgresql::streaming_replication
- masterhost: required, postgres master
- masterusername: required, replication username
- masterpassword: required, replication password
- masterport (default: port_default)
- datadir (default: datadir_default)
- restore_command: (default: undef)
It requires to have pg_basebackup and the defined username already created on the master DB
usage example:
class { 'postgresql::streaming_replication':
masterhost => '192.168.56.29',
masterusername => 'replicator',
masterpassword => 'replicatorpassword',
}
postgresql::pgstatsstatements
Enable pg_stats_statements:
- track_utility: (default: true)
- track: (default: all)
- max: (default: 10000)
usage example:
class { 'postgresql::pgstatsstatements': }
defines
postgresql::role
manages roles (alias users):
- rolename: role to define (default: resource's name)
- password: password for this role (if it's not a group)
- login: boolean, enable or disable login grant (default: true)
- superuser boolean, enable or disable superuser grant (default: false)
- replication boolean, enable or disable replication grant (default: false)
usage example:
postgresql::role { 'jordi':
superuser => true,
password => 'fuckyeah',
}
postgresql::schema
Manages schemas:
- schemaname: schema to create (default: resource's name)
- owner: required, schema's owner
usage example:
postgresql::schema { 'jordidb':
owner => 'jordi',
}
postgresql::hba_rule
creates rules to pg_hba:
-
user: "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.
-
database: "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).
-
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.
-
type: it can be set to:
- 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
- hostnossl is a plain TCP/IP socket. (default: host)
-
auth_method: can be:
- trust
- reject
- md5 (default)
- password (clear text passwords!)
- gss
- sspi
- krb5
- ident
- peer
- pam
- ldap
- radius
- cert
-
auth_option: set of options for the authentication in the format NAME=VALUE. The available options depend on the different authentication methods(default: undef)
-
description: description to identify each rule, see example below (default: resource's name)
-
order: if any (default: 01)
usage example:
postgresql::hba_rule { 'test':
user => 'replicator',
database => 'replication',
address => '192.168.56.0/24',
}
It will create the following pg_hba rule:
# rule: test
host replication replicator 192.168.56.30/32 md5
postgresql::pgdumpbackup
- destination: path to store backups
- pgroot: Postgres installation base (default: undef)
- instance: postgres instance (default: undef)
- retention: (default: 7)
- dbs: dbs to backup (default: ALL)
- mailto: notify by mail (default: undef)
- idhost: host ID, if this variabla is set to undef, it will use it's fqdn
- basedir: path to install the backup script (default: /usr/local/bin)
- ensure: presence or absence of this backup script (default: present)
- username: user to perform backups (default: postgres)
- cron settings:
- setcronjob: create a cronjob (default: true)
- hour_cronjob: hour (default: 2)
- minute_cronjob: minute (default: 0)
- month_cronjob: month (default: undef)
- monthday_cronjob: monthday (default: undef)
- weekday_cronjob: weekday (default: undef)
example setup:
postgresql::pgdumpbackup { "backup logic":
destination => '/backup',
mailto => 'backup_notifications@systemadmin.es',
idhost => 'postgresmaster01',
}
postgresql::backup::pgsnapshot
Backups using pgsnapshot:
- ensure: Whether the cronjob and the script itseld should be in the system (default: present)
- username: Postgre's username (default: postgres)
- backupname: Backup job name (default: resource's name)
- mailto: Send a backup report to this address (default: undef)
- idhost: Force a specific host id (default: undef, server's FQDN)
- basedir: Where to install backup script (default: /usr/local/bin)
- confdir: Where to store configuration file (default: /etc)
- lvm_disk: Use a specific LVM disk (default: undef, connect to postgres to get the actual datadir)
- aws: Use AWS snapshots (default: false)
- snap_size: Snapshot size - recommended to be large if you plan to keep snapshots and small if you plan to use AWS snapshots (default: 5G)
- keeplvmsnaps: How many LVM snapshots to keep (default: 2)
- keep_aws_snaps_days: Delete AWS snapshots older than N days (default: 7)
- snapshot_basename: LVM snapshot basename (default: pgsnap)
- logdir: Log directory (default: /var/log/pgsnapshot)
- force_ami: Force a specific AMI for the restored instance (default: undef, use the same AMI as the running instance)
- cron settings:
- setcronjob: create a cronjob (default: true)
- hour_cronjob: hour (default: 2)
- minute_cronjob: minute (default: 0)
- month_cronjob: month (default: undef)
- monthday_cronjob: monthday (default: undef)
- weekday_cronjob: weekday (default: undef)
Limitations
Tested in CentOS 6 and 7
Development
We are pushing to have acceptance testing in place, so any new feature should have some tests to check both presence and absence of any feature
TODO
- Add more postgres versions
- Tablespace management
- Improve default config: https://github.com/le0pard/pgtune/blob/master/webpack/selectors/configuration.jsç
- Move postgresql::hba_rule to postgresql::hba namespace
- Add validations for memory settings (KB, MB, GB...)
- Manage replication slots: https://postgresqlspace.wordpress.com/2015/06/18/replication-slots-in-postgres/
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request
What are tasks?
Modules can contain tasks that take action outside of a desired state managed by Puppet. It’s perfect for troubleshooting or deploying one-off changes, distributing scripts to run across your infrastructure, or automating changes that need to happen in a particular order as part of an application deployment.
Tasks in this module release
CHANGELOG
0.5.2
- improved pgbouncer support with better control over the settings
0.5.1
- fix raspbian bug
- fix client dependency
- added support for RHEL/CentOS 8
0.5.0
- added ability to control whether the replica should be paused
- added support for Debian 8, 9 and 10 and Ubuntu 14.04, 16.04, 18.04 and 20.04
0.4.12
- added more autovacuum settings
- added bonjour options
- added checkpoint settings
- added effective_io_concurrency setting; for SSD disks
0.4.11
- added options for setting default local entries on pg_hba
0.4.10
- Updated pg repo URL
0.4.9
- added max_standby_archive_delay and max_standby_streaming_delay
0.4.8
- added compliance check for check_postgres_datadir
0.4.7
- bugfix check_replication_lag
0.4.6
- added nagios compatible check for postgres replication
0.4.5
- Added version dependent flags:
- max_worker_processes
- max_parallel_workers
- max_parallel_workers_per_gather
0.4.4
- added pgbouncer support
0.4.2
- fixed systemd::dropin dependency
0.4.1
- added postgis support to PostgreSQL 11
0.4.0
- INCOMPATIBLE CHANGES:
- set default PostgreSQL version to PostgreSQL 11
- version number for postgresql::postgis is now mandatory (there's no default)
- renamed postgresql::streaming_replication to postgresql::recoveryconf. Class postgresql::streaming_replication still exists just for compatibility
- improved recoveryconf management adding more variables
0.3.6
- added inherit flag to postgresql::role
- added install_contrib flag to postgresql
0.3.5
- added default_transaction_read_only under puppet management
0.3.4
- added flag to control autorestart: When a config change requires the service to be restarted it can be done automatically if restart_if_needed is set to true (default: true)
- renamed recovery.conf ERB template
- added support for PostgreSQL 11
0.3.3
- enabled log_lock_waits by default
- added deadlock_timeout variable
- added postgres::repo and postgres::client classes to be able to install postgres client without installing postgres server
0.3.2
- added log_line_prefix
- added compress and purge pg_log directory cronjobs under puppet management
0.3.1
- Updated metadata for eyp-systemd 0.2.0
0.3.0
- Moved pg_reload_conf() from postgresql::hba::reload to postgresql::config::reload
- Postgres config reload on change instead of service restart
- Postgres service will be restarted if there are changes that need to restart the service - /usr/local/bin/check_postgres_pending_restart
- Fixed package name for postgres 10 repo
- INCOMPATIBLE CHANGE:
- enabled wal_compression by default for postgres >= 9.5
0.2.2
- added effective_cache_size variable (default: 3/4 memory size)
- changed default maintenance_work_mem to 64MB
0.2.1
- set timeout for pg_basebackup to 0
0.2.0
- Major rewrite of ::postgresql class - No incompatible change introduced
- pg_hba.conf: reload service on changes instead of service restart
- added a variable to install extension for a specific DB by default for postgresql::pgstatsstatements and postgresql::postgis
0.1.68
- modified default value for archive_mode to true
0.1.67
- added dbname flag to postgresql::extension
- created postgresql::pgstatsstatements::extension and postgresql::postgis::extension to enable these extensions on an arbitrary DB
0.1.66
- changed default max_wal_senders from 0 to 5
0.1.65
- Added service dependency for postgresql::pgdumpbackup
0.1.64
- added postgres 10 support for RHEL 6/7 and CentOS 6/7
- postGIS basic support
0.1.63
- set max_replication_slots to 5 by default
- postgresql::streaming_replication:
- added primary_slot_name and recovery_min_apply_delay
- added postgresql::replication_slot
0.1.62
- bugfix pgsnapshot: set same SubnetId for the restore instances
0.1.60
- improved pgsnapshot: added -R option to be able to list currently running restored instances
0.1.59
- configure vacuum analyze job: postgresql::maintenance::analyze
0.1.58
- added flag to disable postgres.conf management
- disable postgres.conf management on a restored instance via pgsnapshot
0.1.57
- added pgsnapshot.py as backup method
- added flag to disable pg_hba.conf management
0.1.56
- added log related variables:
- log_min_duration_statement
- log_file_mode
0.1.55
- added archive_cleanup_command
0.1.54
- added search_path variable
0.1.53
- minor feature cleanup
0.1.52
- bugfix postgresql::pgdumpbackup
0.1.51
- added extension management via postgtresql::extension
0.1.50
- bugfix: streaming replication ordering
0.1.49
- added postgresql::db
0.1.48
- added autovacuum_freeze_max_age
0.1.47
- added log_autovacuum_min_duration
0.1.46
- bugfix pidfile: wrong default filename
0.1.45
- bugfix datadir on CentOS 7
0.1.44
- dependency bugfix archive command
0.1.43
- dependency bugfix for postgresql::pgstatsstatements
0.1.42
- added ability to change owner to postgresql::schema
0.1.41
- added support for PostgreSQL 9.6
0.1.40
- archive_dir_chmod: changed functionality to chmod all archived files
0.1.39
- force datadir for archive_command
0.1.38
- bugfix archive_dir_chmod
0.1.37
- added support for CentOS 7
0.1.36
- changed chmod order to be done BEFORE copying it to archive_dir
0.1.35
- added archive_dir_chmod, change mode after archiving WALs
0.1.34
- added user, group and mode to archive_dir
- bugfix dependencies
- updated dependency for mkdir archivedir to depend on service
- deleted dependency for cronjob
0.1.28
- restore_command option added to postgresql::streaming_replication (default: undef)
Dependencies
- puppetlabs/stdlib (>= 4.12.0 < 9.9.9)
- puppetlabs/concat (>= 1.2.3 < 9.9.9)
- eyp/systemd (>= 0.1.35 < 0.4.0)
- eyp/python (>= 0.1.0 < 0.2.0)
- eyp/lvm (>= 0.1.0 < 0.2.0)
- eyp/nrpe (>= 0.1.22 < 0.2.0)
- eyp/apt (>= 0.1.11 < 0.2.0)
- eyp/epel (>= 3.1.0 < 4.0.0)
- eyp/eyplib (>= 0.1.0 < 0.2.0)