Setting up PostgreSQL on RDS using ansible is a bit tricky because the main user on RDS is not a SUPERUSER and roles membership is not automatically granted for ex: “ERROR: must be member of role ..” is quite common. Here is a working solution:
- set_fact:
local_ip: "123.456.0.0"
env: staging
postgresql_admin_user: "pgadmin"
postgresql_admin_password: "some_pass"
postgresql_admin_db: "some_db"
postgresql_databases:
- owner: some_user
name: some_db
postgresql_users:
- name: some_user
pass: some_pass
encrypted: no
postgresql_user_privileges:
- name: some_user # user name
db: some_db # database
priv: "ALL" # privilege string format: example: INSERT,UPDATE/table:SELECT/anothertable:ALL
# role_attr_flags: ""
- name: PostgreSQL | Databases security group
ec2_group:
name: "database_{{env}}"
description: "Database security group"
region: "{{ aws_region }}"
vpc_id: "{{vpc_id}}"
purge_rules: False
purge_rules_egress: False
rules:
- proto: tcp
from_port: 5432
to_port: 5432
cidr_ip: "172.31.0.0/16"
- proto: tcp
from_port: 5432
to_port: 5432
cidr_ip: "{{local_ip}}" # your local IP
rules_egress:
- proto: tcp
from_port: 80
to_port: 80
cidr_ip: 0.0.0.0/0
- proto: tcp
from_port: 443
to_port: 443
cidr_ip: 0.0.0.0/0
register: db_security_group
- name: install aws-cli
pip:
name: awscli
state: latest
delegate_to: 127.0.0.1
# issue with full example https://github.com/ansible/ansible-modules-core/issues/633
# most of the variables on this tasks are not present in this file
- name: PostgreSQL | Create an RDS instance in a single availability zone
command: "aws rds create-db-instance
--db-instance-identifier my-postgressql-{{env}}
--db-instance-class {{ postgresql_instance_type }}
--availability-zone {{ postgresql_zone }}
--engine {{ postgresql_engine }}
--engine-version {{ postgresql_engine_version }}
--db-parameter-group-name {{ postgresql_parameter_group }}
--storage-type {{ postgresql_storage }}
--allocated-storage {{ postgresql_size }}
--master-username {{ postgresql_admin_user }}
--master-user-password {{ postgresql_admin_password }}
--db-name {{ postgresql_admin_user }}
--vpc-security-group-ids {{ db_security_group.group_id }}
--preferred-maintenance-window 'Sat:02:00-Sat:06:30'
--auto-minor-version-upgrade
--backup-retention-period 1
--preferred-backup-window '05:00-05:30'
--tags Key=Name,Value={{ instance_name }},Key=Env,Value={{ env }}"
environment:
AWS_ACCESS_KEY_ID: "{{aws_key_id}}"
AWS_SECRET_ACCESS_KEY: "{{aws_secret_key}}"
AWS_DEFAULT_REGION: "{{ aws_region }}"
become_user: root
delegate_to: 127.0.0.1
register: single_zone_result
failed_when: single_zone_result.rc != 0 and ('DBInstanceAlreadyExists' not in single_zone_result.stderr)
changed_when: "single_zone_result.rc == 0"
no_log: True
- name: PostgreSQL | Install psycopg2 locally
pip:
name: psycopg2-binary
state: latest
delegate_to: 127.0.0.1
# make sure you enable RDS in boto ini config
# will need to reload boto cache for this to work
- name: set postgres_host
set_fact:
postgres_host: "{{hostvars[groups['my-postgressql-'+env][0]].ansible_host}}"
- name: PostgreSQL | Make sure the PostgreSQL databases are present
postgresql_db:
name: "{{item.name}}"
encoding: 'UTF-8'
lc_collate: 'en_US.UTF-8'
lc_ctype: 'en_US.UTF-8'
port: 5432
template: "{{postgresql_admin_db}}" //to allow full ownership of new databases
state: present
login_host: "{{ postgres_host }}"
login_user: "{{postgresql_admin_user}}"
login_password: "{{ postgresql_admin_password }}"
delegate_to: 127.0.0.1
with_items: "{{postgresql_databases}}"
no_log: True
- name: PostgreSQL | Make sure the PostgreSQL users are present
postgresql_user:
name: "{{item.name}}"
password: "{{ item.pass }}"
encrypted: yes
port: 5432
state: present
login_host: "{{ postgres_host }}"
login_user: "{{postgresql_admin_user}}"
login_password: "{{ postgresql_admin_password }}"
with_items: "{{postgresql_users}}"
delegate_to: 127.0.0.1
no_log: True
- name: PostgreSQL | Update the user privileges
postgresql_user:
name: "{{item.name}}"
db: "{{item.db}}"
priv: "{{item.priv}}"
role_attr_flags: "{{item.role_attr_flags | default(omit)}}"
port: 5432
state: present
login_host: "{{ postgres_host }}"
login_user: "{{postgresql_admin_user}}"
login_password: "{{ postgresql_admin_password }}"
with_items: "{{postgresql_user_privileges}}"
delegate_to: 127.0.0.1
no_log: True
- name: PostgreSQL | Update databases owners
postgresql_db:
name: "{{item.name}}"
owner: "{{item.owner}}"
state: present
port: 5432
login_host: "{{ postgres_host }}"
login_user: "{{postgresql_admin_user}}"
login_password: "{{ postgresql_admin_password }}"
delegate_to: 127.0.0.1
with_items: "{{postgresql_databases}}"
no_log: True