From 19c75d2e0902c90a35dcdc8aebb9de2438c89c42 Mon Sep 17 00:00:00 2001 From: "A. Hayee Bhatti" Date: Thu, 13 Aug 2026 17:33:24 +0500 Subject: [PATCH 1/2] Allow-list spock_output for affected PostgreSQL minors Recent PostgreSQL minor releases (15.19 / 16.15 / 17.11 and later) added the output_plugin_libraries allow-list, defaulting to 'pgoutput, test_decoding'. Third-party output plugins are refused unless listed, so Spock's spock_output can no longer be used by default: on the provider the replication slot can't be created and replication stops. Add version-gated, per-PG-major handling that ensures spock_output is allow-listed without disturbing existing configuration: - PG upgrade: when upgrading base Postgres to an affected minor and Spock 5.x is already installed for that PG, add spock_output before the existing restart (skipped entirely when Spock is not installed). - Spock install/upgrade: when the target PG minor is affected, add spock_output before create_extension() performs its restart. Existing entries are preserved and spock_output is appended only if missing; when the parameter is absent (e.g. an upgraded conf that predates it) the stock plugins are seeded so they are never dropped. All checks are scoped per PG major so side-by-side installs are independent. No additional server stops/restarts are introduced. --- cli/scripts/cli.py | 4 +++ cli/scripts/util.py | 88 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/cli/scripts/cli.py b/cli/scripts/cli.py index 3a99780b..38190f09 100644 --- a/cli/scripts/cli.py +++ b/cli/scripts/cli.py @@ -542,6 +542,10 @@ def upgrade_component(p_comp): os.environ[p_comp + "_update_version"] = update_version if rc == 0: meta.update_component_version(p_comp, update_version) + # Upgrading base Postgres to an affected minor: if Spock 5.x is already + # installed for this PG, allow-list spock_output before the restart below. + if re.match(r"^pg\d+$", p_comp): + util.maybe_enable_spock_output(p_comp, require_spock_installed=True) util.run_script(p_comp, "update-" + p_comp, "update") if isJSON: msg = ( diff --git a/cli/scripts/util.py b/cli/scripts/util.py index 3a4dfee8..a2a1ad59 100644 --- a/cli/scripts/util.py +++ b/cli/scripts/util.py @@ -206,6 +206,89 @@ def guc_value_as_bool(guc_value): _SPOCK5_NAME_RE = re.compile(r"^spock5(?:0)?(?:-pg\d+)?$", re.IGNORECASE) _SPOCK5_VER_RE = re.compile(r"^5\.", re.IGNORECASE) +# PG's Nov-2025 security releases added the output_plugin_libraries allow-list +# (default 'pgoutput, test_decoding'). spock_output has to be permitted or Spock +# can't create its replication slot. Minimum affected minor per major: +_OUTPUT_PLUGIN_MIN_MINOR = {15: 19, 16: 15, 17: 11} +_SPOCK_OUTPUT_PLUGIN = "spock_output" +# Stock plugins seeded when the GUC isn't configured at all, so we never drop +# them while adding spock_output. +_DEFAULT_OUTPUT_PLUGINS = "pgoutput, test_decoding" + + +def pg_minor_needs_output_plugin(pg_comp): + """ + True when pg_comp's installed minor is at/above the release that introduced + the output_plugin_libraries allow-list (PG 15.19 / 16.15 / 17.11+). + """ + ver = meta.get_version(pg_comp) + if not ver: + return False + try: + v = Version.coerce(str(ver)) + except Exception: + return False + min_minor = _OUTPUT_PLUGIN_MIN_MINOR.get(v.major) + if min_minor is None: + return False + return v.minor >= min_minor + + +def spock5_installed_for_pg(pg_comp): + """ + True when a Spock 5.x extension is installed for this specific PG major + (e.g. spock50-pg17 for pg17). Scoped by the -pgNN suffix so side-by-side + PG installs don't cross-trigger. + """ + try: + c = cL.cursor() + c.execute( + "SELECT 1 FROM components " + "WHERE component LIKE ? AND version LIKE '5.%' LIMIT 1", + ["spock5%-" + str(pg_comp)], + ) + return c.fetchone() is not None + except Exception: + return False + + +def ensure_spock_output_plugin(pg_comp): + """ + Make sure output_plugin_libraries permits spock_output on pg_comp, preserving + anything already configured. No-op when spock_output is already present; when + the parameter isn't set at all (e.g. an upgraded conf that predates it) the + stock plugins are seeded alongside spock_output. Writes postgresql.conf only; + the new value is picked up by the restart the caller already performs. + """ + current = get_guc_value(pg_comp, "output_plugin_libraries") + + if current: + if _SPOCK_OUTPUT_PLUGIN in current.replace(",", " ").split(): + return + new_val = current.strip() + ", " + _SPOCK_OUTPUT_PLUGIN + else: + new_val = _DEFAULT_OUTPUT_PLUGINS + ", " + _SPOCK_OUTPUT_PLUGIN + + message("Allow-listing " + _SPOCK_OUTPUT_PLUGIN + " in output_plugin_libraries for " + str(pg_comp)) + # new_val already carries every existing entry, so replace the line wholesale. + change_pgconf_keyval(pg_comp, "output_plugin_libraries", new_val, True) + + +def maybe_enable_spock_output(pg_comp, require_spock_installed=False): + """ + Single gate for the spock_output / output_plugin_libraries handling. Only + acts when pg_comp is on an affected PG minor; when require_spock_installed is + set (the PG-upgrade path) it also confirms Spock 5.x is installed for this + same PG major first. Everything is scoped to pg_comp, so side-by-side PG + majors are handled independently. + """ + if not pg_minor_needs_output_plugin(pg_comp): + return + if require_spock_installed and not spock5_installed_for_pg(pg_comp): + return + ensure_spock_output_plugin(pg_comp) + + def validate_spock_upgrade(spock_component): """ Validate Spock↔PostgreSQL compatibility for an upcoming Spock 5 install. @@ -1277,6 +1360,11 @@ def config_extension(p_pg=None, p_comp=None): else: change_pgconf_keyval(p_pg, str(df_l[0]), str(df_l[1]), True) + # Installing/upgrading Spock 5.x on an affected PG minor: allow-list + # spock_output before create_extension() drives the restart below. + if _SPOCK5_NAME_RE.match(str(p_comp)): + maybe_enable_spock_output(pgV) + rc = create_extension(p_pg, p_ext=preload_name, p_extension=extension_name, p_enable=True) if rc is True: return(0) From 7ea7e7e69083a1ceb2588c13ca105670b02154e0 Mon Sep 17 00:00:00 2001 From: hayee-bhatti Date: Thu, 13 Aug 2026 16:03:49 +0000 Subject: [PATCH 2/2] PG version bumps to 17.11, 16.15 and 15.19. CLI to 25.7.0 --- cli/scripts/install.py | 2 +- cli/scripts/util.py | 2 +- env.sh | 10 +++++----- src/conf/versions.sql | 11 +++++++---- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/cli/scripts/install.py b/cli/scripts/install.py index 8a2e3b73..8ce0e1e8 100644 --- a/cli/scripts/install.py +++ b/cli/scripts/install.py @@ -3,7 +3,7 @@ import sys, os, tarfile, platform -VER = "25.6.3" +VER = "25.7.0" REPO = os.getenv("REPO", "https://downloads.pgedge.com/platform/repos/download") if sys.version_info < (3, 9): diff --git a/cli/scripts/util.py b/cli/scripts/util.py index a2a1ad59..8d709428 100644 --- a/cli/scripts/util.py +++ b/cli/scripts/util.py @@ -4,7 +4,7 @@ import os import time -MY_VERSION = "25.6.3" +MY_VERSION = "25.7.0" MY_CODENAME = "" DEFAULT_PG = "17" diff --git a/env.sh b/env.sh index adf6027b..1dea7b4f 100755 --- a/env.sh +++ b/env.sh @@ -1,5 +1,5 @@ -hubV=25.6.3 -hubVV=25.6.3 +hubV=25.7.0 +hubVV=25.7.0 aceV=$hubV kirkV=$hubV @@ -23,13 +23,13 @@ removeComponentFromOut=spock60 lolorV=1.2.2-1 snwflkV=2.4-1 -P17=17.10-1 +P17=17.11-1 P171=17.0-1 -P16=16.14-1 +P16=16.15-1 P161=16.4-2 -P15=15.18-1 +P15=15.19-1 P151=15.8-2 vectorV=0.8.1-1 diff --git a/src/conf/versions.sql b/src/conf/versions.sql index 006f3961..f6b043ad 100644 --- a/src/conf/versions.sql +++ b/src/conf/versions.sql @@ -1,7 +1,7 @@ DROP TABLE IF EXISTS hub; CREATE TABLE hub(v TEXT NOT NULL PRIMARY KEY, c TEXT NOT NULL, d TEXT NOT NULL); -INSERT INTO hub VALUES ('25.6.1', '', '20260624'); +INSERT INTO hub VALUES ('25.7.0', '', '20260624'); DROP VIEW IF EXISTS v_versions; DROP VIEW IF EXISTS v_products; @@ -152,21 +152,24 @@ INSERT INTO projects VALUES ('pg', 'pge', 1, 5432, '', 1, 'https://github.com/po INSERT INTO releases VALUES ('pg15', 2, 'pg', '', '', 'prod', 'New in 2022', 1, 'POSTGRES', '', ''); -INSERT INTO versions VALUES ('pg15', '15.18-1', 'amd', 1, '20260514','', '', ''); +INSERT INTO versions VALUES ('pg15', '15.19-1', 'amd', 1, '20260714','', '', ''); +INSERT INTO versions VALUES ('pg15', '15.18-1', 'amd', 0, '20260514','', '', ''); INSERT INTO versions VALUES ('pg15', '15.17-1', 'amd, arm', 0, '20260226','', '', ''); INSERT INTO versions VALUES ('pg15', '15.16-1', 'amd, arm', 0, '20260211','', '', ''); INSERT INTO versions VALUES ('pg15', '15.15-1', 'amd, arm', 0, '20251113','', '', ''); INSERT INTO releases VALUES ('pg16', 2, 'pg', '', '', 'prod', 'New in 2023!', 1, 'POSTGRES', '', ''); -INSERT INTO versions VALUES ('pg16', '16.14-1', 'amd', 1, '20260514','', '', ''); +INSERT INTO versions VALUES ('pg16', '16.15-1', 'amd', 1, '20260714','', '', ''); +INSERT INTO versions VALUES ('pg16', '16.14-1', 'amd', 0, '20260514','', '', ''); INSERT INTO versions VALUES ('pg16', '16.13-1', 'amd, arm', 0, '20260226','', '', ''); INSERT INTO versions VALUES ('pg16', '16.12-1', 'amd, arm', 0, '20260211','', '', ''); INSERT INTO versions VALUES ('pg16', '16.11-1', 'amd, arm', 0, '20251113','', '', ''); INSERT INTO releases VALUES ('pg17', 2, 'pg', '', '', 'prod', 'New in 2024!', 1, 'POSTGRES', '', ''); -INSERT INTO versions VALUES ('pg17', '17.10-1', 'amd', 1, '20260514','', '', ''); +INSERT INTO versions VALUES ('pg17', '17.11-1', 'amd', 1, '20260714','', '', ''); +INSERT INTO versions VALUES ('pg17', '17.10-1', 'amd', 0, '20260514','', '', ''); INSERT INTO versions VALUES ('pg17', '17.9-1', 'amd, arm', 0, '20260226','', '', ''); INSERT INTO versions VALUES ('pg17', '17.8-1', 'amd, arm', 0, '20260211','', '', ''); INSERT INTO versions VALUES ('pg17', '17.7-1', 'amd, arm', 0, '20251113','', '', '');