While these modules are really nice and helpful, we can't use them for at least 2 reasons: - for us, Postgres runs in a container on a private Docker network (`--network=matrix`) without usually being exposed to the host. These modules execute on the host so they won't be able to reach it. - these modules require `psycopg2`, so we need to install it before using it. This might or might not be its own can of worms.pull/740/head
| @@ -0,0 +1,34 @@ | |||||
| --- | |||||
| # TODO - ensure `additional_db` contains all keys that we expect | |||||
| # The SQL statements that we'll run against Postgres are stored in a file that others can't read. | |||||
| # This file will be mounted into the container and fed to Postgres. | |||||
| # This way, we avoid passing sensitive data around in CLI commands that other users on the system can see. | |||||
| - name: Create additional database initialization SQL file for {{ additional_db.name }} | |||||
| template: | |||||
| src: "{{ role_path }}/templates/init-additional-db-user-and-role.sql.j2" | |||||
| dest: "/tmp/matrix-postgres-init-additional-db-user-and-role.sql" | |||||
| mode: 0600 | |||||
| owner: "{{ matrix_user_uid }}" | |||||
| group: "{{ matrix_user_gid }}" | |||||
| - name: Execute Postgres additional database initialization SQL file for {{ additional_db.name }} | |||||
| command: | |||||
| cmd: >- | |||||
| {{ matrix_host_command_docker }} run | |||||
| --rm | |||||
| --user={{ matrix_user_uid }}:{{ matrix_user_gid }} | |||||
| --cap-drop=ALL | |||||
| --env-file={{ matrix_postgres_base_path }}/env-postgres-psql | |||||
| --network {{ matrix_docker_network }} | |||||
| --mount type=bind,src=/tmp/matrix-postgres-init-additional-db-user-and-role.sql,dst=/matrix-postgres-init-additional-db-user-and-role.sql,ro | |||||
| --entrypoint=/bin/sh | |||||
| {{ matrix_postgres_docker_image_to_use }} | |||||
| -c | |||||
| 'psql -h {{ matrix_postgres_connection_hostname }} --file=/matrix-postgres-init-additional-db-user-and-role.sql' | |||||
| - name: Delete additional database initialization SQL file for {{ additional_db.name }} | |||||
| file: | |||||
| path: /tmp/matrix-postgres-init-additional-db-user-and-role.sql | |||||
| state: absent | |||||
| @@ -1,28 +1,13 @@ | |||||
| --- | --- | ||||
| - name: Retrieve IP of postgres container | |||||
| command: "{{ matrix_host_command_docker }} inspect matrix-postgres --format='{% raw %}{{ .NetworkSettings.Networks.{% endraw %}{{ matrix_docker_network }}{% raw %}.IPAddress }}{% endraw %}'" | |||||
| register: matrix_postgres_container_ip | |||||
| # TODO - we should ensure matrix-postgres.service is started. | |||||
| # .. and that if we had just started it, we've given it ample time to initialize, | |||||
| # before we attempt to run queries against it. | |||||
| - name: Create additional users in postgres | |||||
| postgresql_user: | |||||
| name: "{{ item.username }}" | |||||
| password: "{{ item.pass }}" | |||||
| login_host: "{{ matrix_postgres_container_ip.stdout }}" | |||||
| login_port: 5432 | |||||
| login_user: "{{ matrix_postgres_connection_username }}" | |||||
| login_password: "{{ matrix_postgres_connection_password }}" | |||||
| login_db: "{{ matrix_postgres_db_name }}" | |||||
| loop: "{{ matrix_postgres_additional_databases }}" | |||||
| - name: Create additional users in postgres | |||||
| postgresql_db: | |||||
| name: "{{ item.name }}" | |||||
| owner: "{{ item.username }}" | |||||
| lc_ctype: 'C' | |||||
| lc_collate: 'C' | |||||
| login_host: "{{ matrix_postgres_container_ip.stdout }}" | |||||
| login_port: 5432 | |||||
| login_user: "{{ matrix_postgres_connection_username }}" | |||||
| login_password: "{{ matrix_postgres_connection_password }}" | |||||
| loop: "{{ matrix_postgres_additional_databases }}" | |||||
| - name: Create additional Postgers user and database | |||||
| include_tasks: "{{ role_path }}/tasks/util/create_additional_database.yml" | |||||
| with_items: "{{ matrix_postgres_additional_databases }}" | |||||
| loop_control: | |||||
| loop_var: additional_db | |||||
| # Suppress logging to avoid dumping the credentials to the shell | |||||
| no_log: true | |||||
| @@ -0,0 +1,19 @@ | |||||
| -- `CREATE USER` does not support `IF NOT EXISTS`, so we use this workaround to prevent an error and raise a notice instead. | |||||
| -- Seen here: https://stackoverflow.com/a/49858797 | |||||
| DO $$ | |||||
| BEGIN | |||||
| CREATE USER {{ additional_db.username }}; | |||||
| EXCEPTION WHEN DUPLICATE_OBJECT THEN | |||||
| RAISE NOTICE 'not creating role {{ additional_db.username }}, since it already exists'; | |||||
| END | |||||
| $$; | |||||
| -- This is useful for initial user creation (since we don't assign a password above) and for handling subsequent password changes | |||||
| -- TODO - we should escape quotes in the password. | |||||
| ALTER ROLE {{ additional_db.username }} PASSWORD '{{ additional_db.pass }}'; | |||||
| -- This will generate an error on subsequent execution | |||||
| CREATE DATABASE {{ additional_db.name }} WITH LC_CTYPE 'C' LC_COLLATE 'C' OWNER {{ additional_db.username }}; | |||||
| -- This is useful for changing the database owner subsequently | |||||
| ALTER DATABASE {{ additional_db.name }} OWNER TO {{ additional_db.username }}; | |||||