@@ -510,12 +510,24 @@ def test_postgrest_ending_empty_key_query_parameter_is_removed(host):
510510
511511
512512def test_postgresql_version (host ):
513- """Print the PostgreSQL version being tested."""
513+ """Print the PostgreSQL version being tested and ensure it's >= 14 ."""
514514 result = run_ssh_command (host ['ssh' ], "sudo -u postgres psql -c 'SELECT version();'" )
515515 if result ['succeeded' ]:
516516 print (f"\n PostgreSQL Version:\n { result ['stdout' ]} " )
517+ # Extract version number from the output
518+ version_line = result ['stdout' ].strip ().split ('\n ' )[2 ] # Skip header and get the actual version
519+ # Extract major version number (e.g., "15.8" -> 15)
520+ import re
521+ version_match = re .search (r'PostgreSQL (\d+)\.' , version_line )
522+ if version_match :
523+ major_version = int (version_match .group (1 ))
524+ print (f"PostgreSQL major version: { major_version } " )
525+ assert major_version >= 14 , f"PostgreSQL version { major_version } is less than 14"
526+ else :
527+ assert False , "Could not parse PostgreSQL version number"
517528 else :
518529 print (f"\n Failed to get PostgreSQL version: { result ['stderr' ]} " )
530+ assert False , "Failed to get PostgreSQL version"
519531
520532 # Also get the version from the command line
521533 result = run_ssh_command (host ['ssh' ], "sudo -u postgres psql --version" )
@@ -524,27 +536,182 @@ def test_postgresql_version(host):
524536 else :
525537 print (f"Failed to get PostgreSQL client version: { result ['stderr' ]} " )
526538
539+ print ("✓ PostgreSQL version is >= 14" )
540+
541+
542+ def test_libpq5_version (host ):
543+ """Print the libpq5 version installed."""
544+ # Try different package managers to find libpq5
545+ result = run_ssh_command (host ['ssh' ], "dpkg -l | grep libpq5 || true" )
546+ if result ['succeeded' ] and result ['stdout' ].strip ():
547+ print (f"\n libpq5 package info:\n { result ['stdout' ]} " )
548+ else :
549+ print ("\n libpq5 not found via dpkg" )
550+
551+ # Also try to find libpq.so files
552+ result = run_ssh_command (host ['ssh' ], "find /usr -name '*libpq*' -type f 2>/dev/null | head -10" )
553+ if result ['succeeded' ] and result ['stdout' ].strip ():
554+ print (f"\n libpq files found:\n { result ['stdout' ]} " )
555+ else :
556+ print ("\n No libpq files found" )
557+
558+ # Check if we can get version from a libpq file
559+ result = run_ssh_command (host ['ssh' ], "ldd /usr/bin/psql | grep libpq || true" )
560+ if result ['succeeded' ] and result ['stdout' ].strip ():
561+ print (f"\n psql libpq dependency:\n { result ['stdout' ]} " )
562+ else :
563+ print ("\n Could not find libpq dependency for psql" )
564+
527565 # This test always passes, it's just for informational purposes
528566 assert True
529567
530568
531- def test_postgrest_logs_no_target_session_attrs_error (host ):
532- """Check that PostgREST logs don't contain the target_session_attrs error."""
533- # Check recent PostgREST logs for the specific error
534- result = run_ssh_command (host ['ssh' ], "sudo journalctl -u postgrest --since '1 hour ago' | grep -i 'target_session_attrs' || true" )
569+ def test_postgrest_read_only_session_attrs (host ):
570+ """Test PostgREST with target_session_attrs=read-only and check for session errors."""
571+ # First, check if PostgreSQL is configured for read-only mode
572+ result = run_ssh_command (host ['ssh' ], "sudo -u postgres psql -c \" SHOW default_transaction_read_only;\" " )
573+ if result ['succeeded' ]:
574+ default_read_only = result ['stdout' ].strip ()
575+ print (f"PostgreSQL default_transaction_read_only: { default_read_only } " )
576+ else :
577+ print ("Could not check PostgreSQL read-only setting" )
578+ default_read_only = "unknown"
579+
580+ # Check if PostgreSQL is in recovery mode (standby)
581+ result = run_ssh_command (host ['ssh' ], "sudo -u postgres psql -c \" SELECT pg_is_in_recovery();\" " )
582+ if result ['succeeded' ]:
583+ in_recovery = result ['stdout' ].strip ()
584+ print (f"PostgreSQL pg_is_in_recovery: { in_recovery } " )
585+ else :
586+ print ("Could not check PostgreSQL recovery status" )
587+ in_recovery = "unknown"
535588
536- if result ['stdout' ].strip ():
537- print (f"\n Found target_session_attrs errors in PostgREST logs:\n { result ['stdout' ]} " )
538- assert False , "PostgREST logs contain target_session_attrs errors"
589+ # Find PostgreSQL configuration file
590+ result = run_ssh_command (host ['ssh' ], "sudo -u postgres psql -c \" SHOW config_file;\" " )
591+ if result ['succeeded' ]:
592+ config_file = result ['stdout' ].strip ().split ('\n ' )[2 ].strip () # Skip header and get the actual path
593+ print (f"PostgreSQL config file: { config_file } " )
539594 else :
540- print ("\n No target_session_attrs errors found in PostgREST logs" )
595+ print ("Could not find PostgreSQL config file" )
596+ config_file = "/etc/postgresql/15/main/postgresql.conf" # Default fallback
597+
598+ # Backup PostgreSQL config
599+ result = run_ssh_command (host ['ssh' ], f"sudo cp { config_file } { config_file } .backup" )
600+ assert result ['succeeded' ], "Failed to backup PostgreSQL config"
601+
602+ # Add read-only setting to PostgreSQL config
603+ result = run_ssh_command (host ['ssh' ], f"echo 'default_transaction_read_only = on' | sudo tee -a { config_file } " )
604+ assert result ['succeeded' ], "Failed to add read-only setting to PostgreSQL config"
605+
606+ # Restart PostgreSQL to apply the new configuration
607+ result = run_ssh_command (host ['ssh' ], "sudo systemctl restart postgresql" )
608+ assert result ['succeeded' ], "Failed to restart PostgreSQL"
541609
542- # Also check for the specific error pattern mentioned
543- result = run_ssh_command ( host [ 'ssh' ], "sudo journalctl -u postgrest --since '1 hour ago' | grep -i 'invalid target_session_attrs value.*read-only' || true" )
610+ # Wait for PostgreSQL to start up
611+ sleep ( 5 )
544612
545- if result ['stdout' ].strip ():
546- print (f"\n Found specific target_session_attrs read-only error:\n { result ['stdout' ]} " )
547- assert False , "PostgREST logs contain invalid target_session_attrs read-only error"
613+ # Verify the change took effect
614+ result = run_ssh_command (host ['ssh' ], "sudo -u postgres psql -c \" SHOW default_transaction_read_only;\" " )
615+ if result ['succeeded' ]:
616+ new_default_read_only = result ['stdout' ].strip ()
617+ print (f"PostgreSQL default_transaction_read_only after change: { new_default_read_only } " )
548618 else :
549- print ("No invalid target_session_attrs read-only errors found in PostgREST logs" )
619+ print ("Could not verify PostgreSQL read-only setting change" )
620+
621+ # First, backup the current PostgREST config
622+ result = run_ssh_command (host ['ssh' ], "sudo cp /etc/postgrest/base.conf /etc/postgrest/base.conf.backup" )
623+ assert result ['succeeded' ], "Failed to backup PostgREST config"
624+
625+ try :
626+ # Read the current config to get the db-uri
627+ result = run_ssh_command (host ['ssh' ], "sudo cat /etc/postgrest/base.conf | grep '^db-uri'" )
628+ assert result ['succeeded' ], "Failed to read current db-uri"
629+
630+ current_db_uri = result ['stdout' ].strip ()
631+ print (f"Current db-uri: { current_db_uri } " )
632+
633+ # Extract just the URI part (remove the db-uri = " prefix and trailing quote)
634+ uri_start = current_db_uri .find ('"' ) + 1
635+ uri_end = current_db_uri .rfind ('"' )
636+ base_uri = current_db_uri [uri_start :uri_end ]
637+
638+ # Modify the URI to add target_session_attrs=read-only
639+ if '?' in base_uri :
640+ # URI already has parameters, add target_session_attrs
641+ modified_uri = base_uri + "&target_session_attrs=read-only"
642+ else :
643+ # URI has no parameters, add target_session_attrs
644+ modified_uri = base_uri + "?target_session_attrs=read-only"
645+
646+ print (f"Modified URI: { modified_uri } " )
647+
648+ # Use awk to replace the db-uri line more reliably
649+ result = run_ssh_command (host ['ssh' ], f"sudo awk '{{if ($1 == \" db-uri\" ) print \" db-uri = \\ \" { modified_uri } \\ \" \" ; else print $0}}' /etc/postgrest/base.conf > /tmp/new_base.conf && sudo mv /tmp/new_base.conf /etc/postgrest/base.conf" )
650+ assert result ['succeeded' ], "Failed to update db-uri in config"
651+
652+ # Verify the change was made correctly
653+ result = run_ssh_command (host ['ssh' ], "sudo cat /etc/postgrest/base.conf | grep '^db-uri'" )
654+ print (f"Updated db-uri line: { result ['stdout' ].strip ()} " )
655+
656+ # Also show the full config to debug
657+ result = run_ssh_command (host ['ssh' ], "sudo cat /etc/postgrest/base.conf" )
658+ print (f"Full config after change:\n { result ['stdout' ]} " )
659+
660+ # Restart PostgREST to apply the new configuration
661+ result = run_ssh_command (host ['ssh' ], "sudo systemctl restart postgrest" )
662+ assert result ['succeeded' ], "Failed to restart PostgREST"
663+
664+ # Wait a moment for PostgREST to start up
665+ sleep (5 )
666+
667+ # Check if PostgREST is running
668+ result = run_ssh_command (host ['ssh' ], "sudo systemctl is-active postgrest" )
669+ if not (result ['succeeded' ] and result ['stdout' ].strip () == 'active' ):
670+ # If PostgREST failed to start, check the logs to see why
671+ log_result = run_ssh_command (host ['ssh' ], "sudo journalctl -u postgrest --since '5 minutes ago' --no-pager" )
672+ print (f"PostgREST failed to start. Recent logs:\n { log_result ['stdout' ]} " )
673+ assert False , "PostgREST failed to start after config change"
674+
675+ # Make a test request to trigger any potential session errors
676+ try :
677+ response = requests .get (
678+ f"http://{ host ['ip' ]} /rest/v1/" ,
679+ headers = {"apikey" : anon_key , "authorization" : f"Bearer { anon_key } " },
680+ timeout = 10
681+ )
682+ print (f"Test request status: { response .status_code } " )
683+ except Exception as e :
684+ print (f"Test request failed: { str (e )} " )
685+
686+ # Check PostgREST logs for "session is not read-only" errors
687+ result = run_ssh_command (host ['ssh' ], "sudo journalctl -u postgrest --since '5 minutes ago' | grep -i 'session is not read-only' || true" )
688+
689+ if result ['stdout' ].strip ():
690+ print (f"\n Found 'session is not read-only' errors in PostgREST logs:\n { result ['stdout' ]} " )
691+ assert False , "PostgREST logs contain 'session is not read-only' errors even though PostgreSQL is configured for read-only mode"
692+ else :
693+ print ("\n No 'session is not read-only' errors found in PostgREST logs" )
694+
695+ finally :
696+ # Restore the original configuration
697+ result = run_ssh_command (host ['ssh' ], "sudo cp /etc/postgrest/base.conf.backup /etc/postgrest/base.conf" )
698+ if result ['succeeded' ]:
699+ result = run_ssh_command (host ['ssh' ], "sudo systemctl restart postgrest" )
700+ if result ['succeeded' ]:
701+ print ("Restored original PostgREST configuration" )
702+ else :
703+ print ("Warning: Failed to restart PostgREST after restoring config" )
704+ else :
705+ print ("Warning: Failed to restore original PostgREST configuration" )
706+
707+ # Restore PostgreSQL to original configuration
708+ result = run_ssh_command (host ['ssh' ], f"sudo cp { config_file } .backup { config_file } " )
709+ if result ['succeeded' ]:
710+ result = run_ssh_command (host ['ssh' ], "sudo systemctl restart postgresql" )
711+ if result ['succeeded' ]:
712+ print ("Restored PostgreSQL to original configuration" )
713+ else :
714+ print ("Warning: Failed to restart PostgreSQL after restoring config" )
715+ else :
716+ print ("Warning: Failed to restore PostgreSQL configuration" )
550717
0 commit comments