Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion cli/scripts/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import meta
import time
import sys
import setup_core
import getpass
from tabulate import tabulate # type: ignore
from ipaddress import ip_address
Expand Down Expand Up @@ -1312,7 +1313,9 @@ def init(cluster_name, install=True):
parsed_json = get_cluster_json(cluster_name)
if parsed_json is None:
util.exit_message("Unable to load cluster JSON", 1)

pg_version = db_settings["pg_version"]
spock_ver = db_settings.get("spock_version", util.get_default_spock(pg_version))
util.validate_spock_pg_compat(spock_ver, pg_version)
verbose = parsed_json.get("log_level", "info")

all_nodes = nodes.copy()
Expand Down
1 change: 0 additions & 1 deletion cli/scripts/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,6 @@ def get_default_spock(pgv):
+ pgv
+ "' \n"
+ " AND component LIKE 'spock%'"
+ " AND version not LIKE '%devel%'"
)
try:
c = con.cursor()
Expand Down
3 changes: 2 additions & 1 deletion cli/scripts/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ def setup_pgedge(User=None, Passwd=None, dbName=None, port=None, pg_data=None, p
pg_ver = df_pg

pg_major, pg_minor = setup_core.parse_pg(pg_ver)

# Validate that if Spock ≥5 we're using PG 15.13+, 16.9+ or 17.5+Add commentMore actions
util.validate_spock_pg_compat(spock_ver, pg_ver)
pg_init_options = ""
if pg_data is not None:
pg_data = pg_data.rstrip("/")
Expand Down
114 changes: 112 additions & 2 deletions cli/scripts/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
MY_CODENAME = ""

DEFAULT_PG = "16"
DEFAULT_SPOCK = "40"
DEFAULT_SPOCK_17 = "40"
DEFAULT_SPOCK = "50"
DEFAULT_SPOCK_17 = "50"
MY_CMD = os.getenv("MY_CMD", None)
MY_HOME = os.getenv("MY_HOME", None)
MY_LIBS = f"{MY_HOME}/hub/scripts/lib"
Expand Down Expand Up @@ -37,6 +37,7 @@
import subprocess
import getpass
import filecmp
import re
from subprocess import Popen, PIPE, STDOUT
from datetime import datetime, timedelta
from urllib import request as urllib2
Expand Down Expand Up @@ -124,6 +125,115 @@ def get_default_spock(pgv):
return(DEFAULT_SPOCK)



def validate_spock_pg_compat(spock_ver: str = None, pg_ver: str = None) -> None:
"""
Compatibility rules:
• If Spock < 5.0.0 ⇒ works with any supported PostgreSQL major.
• If Spock ≥ 5.0.0 ⇒
– PG15 must be ≥ 15.13
– PG16 must be ≥ 16.9
– PG17 must be ≥ 17.5

Also supports shorthand Spock strings:
– "50" → "5.0.0", "40" → "4.0.0", etc.
"""
# 0) Fill in defaults if user didn’t pass anything
if not pg_ver:
pg_ver = DEFAULT_PG
if not spock_ver:
maj = int(pg_ver.split(".", 1)[0])
spock_ver = DEFAULT_SPOCK_17 if maj == 17 else DEFAULT_SPOCK

# 0.5) Normalize two-digit shorthand (e.g. "50" → "5.0.0")
m = re.fullmatch(r'(\d)(\d)$', spock_ver)
if m:
spock_ver = f"{int(m.group(1))}.{int(m.group(2))}.0"

# 1) Parse Spock version (abort on bad format)
try:
spv = Version(spock_ver)
except ValueError:
exit_message(f"Invalid Spock version '{spock_ver}'. Aborting.", 1, isJSON)

# 2) If Spock < 5 ⇒ compatible with any PG
if spv.major < 5:
return

# — New block: handle pg_ver with “-1” or “-2” suffix
rev = None
rev_match = re.fullmatch(r'(\d+)\.(\d+)-(1|2)$', pg_ver)
if rev_match:
pg_major = int(rev_match.group(1))
pg_patch = int(rev_match.group(2))
rev = int(rev_match.group(3))

# reject revision “-1” on Spock ≥5
if rev == 1:
exit_message(
f"Error: PostgreSQL {pg_major}.{pg_patch}-1 is not supported with Spock {spv}; "
"please use the “-2” revision instead.",
1,
isJSON
)
# for “-2”, we strip suffix and proceed with pg_major/pg_patch below
# end new block

# 3) Spock ≥ 5 ⇒ enforce minimum‐patch for each PG major
minimum_patches = {
15: 13,
16: 9,
17: 5,
}

# 4) Extract PG major and patch (if not already set by rev_match)
if rev_match:
# pg_major, pg_patch are already set
pass
elif "." not in pg_ver:
# bare-major → use its minimum patch
try:
pg_major = int(pg_ver)
except ValueError:
exit_message(f"Invalid PostgreSQL version '{pg_ver}'. Aborting.", 1, isJSON)
if pg_major not in minimum_patches:
allowed = ", ".join(str(m) for m in minimum_patches)
exit_message(
f"Error: Spock {spv} supports only PostgreSQL majors {allowed}; "
f"you have {pg_major}. Aborting.",
1,
isJSON
)
pg_patch = minimum_patches[pg_major]
else:
parts = pg_ver.split(".", 2)
if len(parts) < 2:
exit_message(f"Invalid PostgreSQL version '{pg_ver}'. Aborting.", 1, isJSON)
try:
pg_major = int(parts[0])
pg_patch = int(parts[1])
except ValueError:
exit_message(f"Invalid PostgreSQL version '{pg_ver}'. Aborting.", 1, isJSON)

# 5) Major must be supported
if pg_major not in minimum_patches:
allowed = ", ".join(str(m) for m in minimum_patches)
exit_message(
f"Error: Spock {spv} supports only PostgreSQL majors {allowed}; "
f"you have {pg_major}. Aborting.",
1,
isJSON
)

# 6) Enforce minimum‐patch
required = minimum_patches[pg_major]
if pg_patch < required:
exit_message(
f"Error: Spock {spv} requires PostgreSQL {pg_major}.{required} or newer; "
f"you have {pg_major}.{pg_patch}. Aborting.",
1,
isJSON
)
def get_cpu_info():
try:
import cpuinfo
Expand Down
22 changes: 3 additions & 19 deletions src/conf/versions.sql
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,6 @@ CREATE TABLE extensions (
preload_name TEXT NOT NULL,
default_conf TEXT NOT NULL
);
INSERT INTO extensions VALUES ('spock33', 'spock', 1, 'spock',
'wal_level=logical | max_worker_processes=12 | max_replication_slots=16 |
max_wal_senders=16 | hot_standby_feedback=on | wal_sender_timeout=5s |
track_commit_timestamp=on | spock.conflict_resolution=last_update_wins |
spock.save_resolutions=on | spock.conflict_log_level=DEBUG');
INSERT INTO extensions VALUES ('spock40', 'spock', 1, 'spock',
'wal_level=logical | max_worker_processes=12 | max_replication_slots=16 |
max_wal_senders=16 | hot_standby_feedback=on | wal_sender_timeout=5s |
Expand Down Expand Up @@ -320,17 +315,6 @@ INSERT INTO versions VALUES ('snowflake-pg17', '2.2-1', 'amd, arm', 1, '20240626
-- ## SPOCK (parent project) ############
INSERT INTO projects VALUES ('spock', 'pge', 4, 0, '', 1, 'https://github.com/pgedge/spock/tags',
'spock', 1, 'spock.png', 'Logical Rep w/ Conflict Resolution', 'https://github.com/pgedge/spock/', 'pg_spock, pgsspock, vulcan');

-- ## SPOCK33 ###########################
INSERT INTO releases VALUES ('spock33-pg15', 4, 'spock', 'Spock', '', 'prod', '', 1, 'pgEdge Community', '', '');
INSERT INTO releases VALUES ('spock33-pg16', 4, 'spock', 'Spock', '', 'prod', '', 1, 'pgEdge Community', '', '');

INSERT INTO versions VALUES ('spock33-pg15', '3.3.6-1', 'amd, arm', 1, '20240820', 'pg15', '', '');
INSERT INTO versions VALUES ('spock33-pg16', '3.3.6-1', 'amd, arm', 1, '20240820', 'pg16', '', '');

INSERT INTO versions VALUES ('spock33-pg15', '3.3.5-1', 'amd, arm', 0, '20240607', 'pg15', '', '');
INSERT INTO versions VALUES ('spock33-pg16', '3.3.5-1', 'amd, arm', 0, '20240607', 'pg16', '', '');

-- ## SPOCK40 ###########################
INSERT INTO releases VALUES ('spock40-pg15', 4, 'spock', 'Spock', '', 'prod', '', 1, 'pgEdge Community', '', '');
INSERT INTO releases VALUES ('spock40-pg16', 4, 'spock', 'Spock', '', 'prod', '', 1, 'pgEdge Community', '', '');
Expand All @@ -350,9 +334,9 @@ INSERT INTO versions VALUES ('spock40-pg17', '4.0.8-1', 'amd, arm', 0, '20241218


-- ## spock50 ###########################
INSERT INTO releases VALUES ('spock50-pg15', 4, 'spock', 'Spock', '', 'test', '', 1, 'pgEdge Community', '', '');
INSERT INTO releases VALUES ('spock50-pg16', 4, 'spock', 'Spock', '', 'test', '', 1, 'pgEdge Community', '', '');
INSERT INTO releases VALUES ('spock50-pg17', 4, 'spock', 'Spock', '', 'test', '', 1, 'pgEdge Community', '', '');
INSERT INTO releases VALUES ('spock50-pg15', 4, 'spock', 'Spock', '', 'prod', '', 1, 'pgEdge Community', '', '');
INSERT INTO releases VALUES ('spock50-pg16', 4, 'spock', 'Spock', '', 'prod', '', 1, 'pgEdge Community', '', '');
INSERT INTO releases VALUES ('spock50-pg17', 4, 'spock', 'Spock', '', 'prod', '', 1, 'pgEdge Community', '', '');

INSERT INTO versions VALUES ('spock50-pg15', '5.0.0-devel1-1', 'amd, arm', 1, '20250521', 'pg15', '', '');
INSERT INTO versions VALUES ('spock50-pg16', '5.0.0-devel1-1', 'amd, arm', 1, '20250521', 'pg16', '', '');
Expand Down