From b9f2d56932d870a9b8bd9b0daacd4f96a9191587 Mon Sep 17 00:00:00 2001 From: Mike Reeves Date: Thu, 14 May 2026 16:37:08 -0400 Subject: [PATCH] Consolidate telegraf postgres SQL into multi-mode script Replace inline psql heredocs in telegraf_users.sls with subcommand dispatcher telegraf_postgres.sh: create_db, group_role, user, retention. --- salt/postgres/telegraf_users.sls | 63 ++-------- salt/postgres/tools/sbin/telegraf_postgres.sh | 108 ++++++++++++++++++ salt/postgres/tools/sbin/telegraf_role.sh | 23 ---- 3 files changed, 117 insertions(+), 77 deletions(-) create mode 100644 salt/postgres/tools/sbin/telegraf_postgres.sh delete mode 100644 salt/postgres/tools/sbin/telegraf_role.sh diff --git a/salt/postgres/telegraf_users.sls b/salt/postgres/telegraf_users.sls index 369e30dbc..4b95ac45b 100644 --- a/salt/postgres/telegraf_users.sls +++ b/salt/postgres/telegraf_users.sls @@ -44,12 +44,10 @@ postgres_wait_ready: # would otherwise never get so_telegraf. postgres_create_telegraf_db: cmd.run: - - name: | - if ! docker exec so-postgres psql -U postgres -tAc "SELECT 1 FROM pg_database WHERE datname='so_telegraf'" | grep -q 1; then - docker exec so-postgres psql -v ON_ERROR_STOP=1 -U postgres -c "CREATE DATABASE so_telegraf" - fi + - name: /usr/sbin/telegraf_postgres.sh create_db - require: - cmd: postgres_wait_ready + - file: postgres_sbin # Provision the shared group role and schema once. Every per-minion role is a # member of so_telegraf, and each Telegraf connection does SET ROLE so_telegraf @@ -57,44 +55,10 @@ postgres_create_telegraf_db: # on first write are owned by the group role and every member can INSERT/SELECT. postgres_telegraf_group_role: cmd.run: - - name: | - docker exec -i so-postgres psql -v ON_ERROR_STOP=1 -U postgres -d so_telegraf <<'EOSQL' - DO $$ - BEGIN - IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'so_telegraf') THEN - CREATE ROLE so_telegraf NOLOGIN; - END IF; - END - $$; - GRANT CONNECT ON DATABASE so_telegraf TO so_telegraf; - CREATE SCHEMA IF NOT EXISTS telegraf AUTHORIZATION so_telegraf; - GRANT USAGE, CREATE ON SCHEMA telegraf TO so_telegraf; - CREATE SCHEMA IF NOT EXISTS partman; - CREATE EXTENSION IF NOT EXISTS pg_partman SCHEMA partman; - CREATE EXTENSION IF NOT EXISTS pg_cron; - -- Telegraf (running as so_telegraf) calls partman.create_parent() - -- on first write of each metric, which needs USAGE on the partman - -- schema, EXECUTE on its functions/procedures, and write access to - -- partman.part_config so it can register new partitioned parents. - GRANT USAGE, CREATE ON SCHEMA partman TO so_telegraf; - GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA partman TO so_telegraf; - GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA partman TO so_telegraf; - GRANT EXECUTE ON ALL PROCEDURES IN SCHEMA partman TO so_telegraf; - -- partman creates per-parent template tables (partman.template_*) at - -- runtime; default privileges extend DML/sequence access to them. - ALTER DEFAULT PRIVILEGES IN SCHEMA partman - GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO so_telegraf; - ALTER DEFAULT PRIVILEGES IN SCHEMA partman - GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO so_telegraf; - -- Hourly partman maintenance. cron.schedule is idempotent by jobname. - SELECT cron.schedule( - 'telegraf-partman-maintenance', - '17 * * * *', - 'CALL partman.run_maintenance_proc()' - ); - EOSQL + - name: /usr/sbin/telegraf_postgres.sh group_role - require: - cmd: postgres_create_telegraf_db + - file: postgres_sbin {% set creds = salt['pillar.get']('telegraf:postgres_creds', {}) %} {% for mid, entry in creds.items() %} @@ -104,7 +68,7 @@ postgres_telegraf_group_role: postgres_telegraf_role_{{ u }}: cmd.run: - - name: /usr/sbin/telegraf_role.sh + - name: /usr/sbin/telegraf_postgres.sh user - env: - ROLE_USER: {{ u }} - ROLE_PASS: {{ p }} @@ -122,21 +86,12 @@ postgres_telegraf_role_{{ u }}: {% set retention = salt['pillar.get']('postgres:telegraf:retention_days', 14) | int %} postgres_telegraf_retention_reconcile: cmd.run: - - name: | - docker exec -i so-postgres psql -v ON_ERROR_STOP=1 -U postgres -d so_telegraf <<'EOSQL' - DO $$ - BEGIN - IF EXISTS (SELECT 1 FROM pg_catalog.pg_extension WHERE extname = 'pg_partman') THEN - UPDATE partman.part_config - SET retention = '{{ retention }} days', - retention_keep_table = false - WHERE parent_table LIKE 'telegraf.%'; - END IF; - END - $$; - EOSQL + - name: /usr/sbin/telegraf_postgres.sh retention + - env: + - RETENTION_DAYS: {{ retention }} - require: - cmd: postgres_telegraf_group_role + - file: postgres_sbin {% endif %} diff --git a/salt/postgres/tools/sbin/telegraf_postgres.sh b/salt/postgres/tools/sbin/telegraf_postgres.sh new file mode 100644 index 000000000..7f2061543 --- /dev/null +++ b/salt/postgres/tools/sbin/telegraf_postgres.sh @@ -0,0 +1,108 @@ +#!/bin/bash +set -e + +# Provision Telegraf state inside the so-postgres container. +# Usage: telegraf_postgres.sh +# create_db Ensure the so_telegraf database exists. +# group_role Provision the so_telegraf group role, telegraf/partman schemas, +# pg_partman, pg_cron, and the hourly partman maintenance job. +# user Create or update a per-minion login role granted to so_telegraf. +# Env: ROLE_USER, ROLE_PASS. +# retention Reconcile partman retention on telegraf parents. +# Env: RETENTION_DAYS. + +cmd="${1:?subcommand required}" + +case "$cmd" in + create_db) + if ! docker exec so-postgres psql -U postgres -tAc \ + "SELECT 1 FROM pg_database WHERE datname='so_telegraf'" | grep -q 1; then + docker exec so-postgres psql -v ON_ERROR_STOP=1 -U postgres \ + -c "CREATE DATABASE so_telegraf" + fi + ;; + + group_role) + docker exec -i so-postgres psql -v ON_ERROR_STOP=1 -U postgres -d so_telegraf <<'EOSQL' +DO $$ +BEGIN + IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'so_telegraf') THEN + CREATE ROLE so_telegraf NOLOGIN; + END IF; +END +$$; +GRANT CONNECT ON DATABASE so_telegraf TO so_telegraf; +CREATE SCHEMA IF NOT EXISTS telegraf AUTHORIZATION so_telegraf; +GRANT USAGE, CREATE ON SCHEMA telegraf TO so_telegraf; +CREATE SCHEMA IF NOT EXISTS partman; +CREATE EXTENSION IF NOT EXISTS pg_partman SCHEMA partman; +CREATE EXTENSION IF NOT EXISTS pg_cron; +-- Telegraf (running as so_telegraf) calls partman.create_parent() +-- on first write of each metric, which needs USAGE on the partman +-- schema, EXECUTE on its functions/procedures, and write access to +-- partman.part_config so it can register new partitioned parents. +GRANT USAGE, CREATE ON SCHEMA partman TO so_telegraf; +GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA partman TO so_telegraf; +GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA partman TO so_telegraf; +GRANT EXECUTE ON ALL PROCEDURES IN SCHEMA partman TO so_telegraf; +-- partman creates per-parent template tables (partman.template_*) at +-- runtime; default privileges extend DML/sequence access to them. +ALTER DEFAULT PRIVILEGES IN SCHEMA partman + GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO so_telegraf; +ALTER DEFAULT PRIVILEGES IN SCHEMA partman + GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO so_telegraf; +-- Hourly partman maintenance. cron.schedule is idempotent by jobname. +SELECT cron.schedule( + 'telegraf-partman-maintenance', + '17 * * * *', + 'CALL partman.run_maintenance_proc()' +); +EOSQL + ;; + + user) + : "${ROLE_USER:?ROLE_USER is required}" + : "${ROLE_PASS:?ROLE_PASS is required}" + docker exec -i so-postgres psql \ + -v ON_ERROR_STOP=1 \ + -v role_user="$ROLE_USER" \ + -v role_pass="$ROLE_PASS" \ + -U postgres -d so_telegraf <<'EOSQL' +DO $$ +BEGIN + IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = :role_user) THEN + EXECUTE format('CREATE ROLE %I WITH LOGIN PASSWORD %L', :role_user, :role_pass); + ELSE + EXECUTE format('ALTER ROLE %I WITH LOGIN PASSWORD %L', :role_user, :role_pass); + END IF; +END +$$; +GRANT CONNECT ON DATABASE so_telegraf TO :"role_user"; +GRANT so_telegraf TO :"role_user"; +EOSQL + ;; + + retention) + : "${RETENTION_DAYS:?RETENTION_DAYS is required}" + docker exec -i so-postgres psql \ + -v ON_ERROR_STOP=1 \ + -v retention_days="$RETENTION_DAYS" \ + -U postgres -d so_telegraf <<'EOSQL' +DO $$ +BEGIN + IF EXISTS (SELECT 1 FROM pg_catalog.pg_extension WHERE extname = 'pg_partman') THEN + UPDATE partman.part_config + SET retention = :'retention_days' || ' days', + retention_keep_table = false + WHERE parent_table LIKE 'telegraf.%'; + END IF; +END +$$; +EOSQL + ;; + + *) + echo "Unknown subcommand: $cmd" >&2 + exit 1 + ;; +esac diff --git a/salt/postgres/tools/sbin/telegraf_role.sh b/salt/postgres/tools/sbin/telegraf_role.sh deleted file mode 100644 index 352efa018..000000000 --- a/salt/postgres/tools/sbin/telegraf_role.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -set -e - -# Provision or update a Telegraf postgres role. -# Expects ROLE_USER and ROLE_PASS environment variables. - -docker exec -i so-postgres psql \ - -v ON_ERROR_STOP=1 \ - -v role_user="$ROLE_USER" \ - -v role_pass="$ROLE_PASS" \ - -U postgres -d so_telegraf <<'EOSQL' -DO $$ -BEGIN - IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = :role_user) THEN - EXECUTE format('CREATE ROLE %I WITH LOGIN PASSWORD %L', :role_user, :role_pass); - ELSE - EXECUTE format('ALTER ROLE %I WITH LOGIN PASSWORD %L', :role_user, :role_pass); - END IF; -END -$$; -GRANT CONNECT ON DATABASE so_telegraf TO :"role_user"; -GRANT so_telegraf TO :"role_user"; -EOSQL