def test_connection_info(): url = "postgres://*****:*****@dbhost.local:5555/abc?replication=true&sslmode=foobar&sslmode=require" cs = "host=dbhost.local user='******' dbname='abc'\n" \ "replication=true password=secret sslmode=require port=5555" ci = { "host": "dbhost.local", "port": "5555", "user": "******", "password": "******", "dbname": "abc", "replication": "true", "sslmode": "require", } assert get_connection_info(ci) == get_connection_info(cs) assert get_connection_info(ci) == get_connection_info(url) basic_cstr = "host=localhost user=os" assert create_connection_string(get_connection_info(basic_cstr)) == "host='localhost' user='******'" assert get_connection_info("foo=bar bar='\\'x'") == {"foo": "bar", "bar": "'x"} with raises(ValueError): get_connection_info("foo=bar x") with raises(ValueError): get_connection_info("foo=bar bar='x")
def test_two_slave_failover_and_autofollow(self): self._add_db_to_cluster_state("old_master", pg_is_in_recovery=False, connection=False, fetch_time=datetime.datetime(year=2014, month=1, day=1)) # We will make our own node to be the furthest from master so we don't get considered for promotion self._add_db_to_cluster_state("own", pg_last_xlog_receive_location="1/aaaaaaaa", pg_is_in_recovery=True, connection=False, replication_time_lag=130.0) self.pglookout.own_db = "own" self._add_db_to_cluster_state("other", pg_last_xlog_receive_location="2/aaaaaaaa", pg_is_in_recovery=True, connection=False, replication_time_lag=130.0) self.pglookout.check_cluster_state() self.assertTrue(self.pglookout.replication_lag_over_warning_limit) # we keep the warning on self.assertEqual(self.pglookout.execute_external_command.call_count, 0) self.assertEqual(self.pglookout.current_master, "old_master") self._add_db_to_cluster_state("other", pg_last_xlog_receive_location="2/aaaaaaaa", pg_is_in_recovery=False, connection=True, replication_time_lag=0.0, conn_info={"host": "otherhost.example.com", "port": 11111}) pg_data_dir = os.path.join(self.temp_dir + os.sep + "test_pgdata") os.makedirs(pg_data_dir) primary_conninfo = "user=replication password=vjsh8l7sv4a902y1tsdz host=old_master port=5432 sslmode=prefer sslcompression=1 krbsrvname=postgres" old_recovery_conf = "standby_mode = 'on'\nprimary_conninfo = '{0}'\n".format(primary_conninfo) with open(os.path.join(pg_data_dir, "recovery.conf"), "w") as fp: fp.write(old_recovery_conf) self.pglookout.config['pg_data_directory'] = pg_data_dir self.pglookout.config['autofollow'] = True self.pglookout.primary_conninfo_template = get_connection_info(primary_conninfo) self.pglookout.check_cluster_state() self.assertEqual(self.pglookout.current_master, "other") with open(os.path.join(pg_data_dir, "recovery.conf"), "r") as fp: new_lines = fp.read().splitlines() assert new_lines.pop(0).startswith("# pglookout updated primary_conninfo") assert new_lines.pop(0) == "standby_mode = 'on'" assert new_lines[0].startswith("primary_conninfo = ") new_primary_conninfo = new_lines.pop(0) assert new_lines.pop(0) == "recovery_target_timeline = 'latest'" assert new_lines == [] old_conn_info = get_connection_info(primary_conninfo) new_conn_info = get_connection_info_from_config_line(new_primary_conninfo) assert new_conn_info == dict(old_conn_info, host="otherhost.example.com", port="11111")
def test_mask_connection_info(): url = "postgres://*****:*****@dbhost.local:5555/abc?replication=true&sslmode=foobar&sslmode=require" cs = "host=dbhost.local user='******' dbname='abc'\n" \ "replication=true password=secret sslmode=require port=5555" ci = get_connection_info(cs) masked_url = mask_connection_info(url) masked_cs = mask_connection_info(url) masked_ci = mask_connection_info(url) assert masked_url == masked_cs assert masked_url == masked_ci assert "password" in ci # make sure we didn't modify the original dict # the return format is a connection string without password, followed by # a semicolon and comment about password presence masked_str, password_info = masked_url.split("; ", 1) assert "password" not in masked_str assert password_info == "hidden password" # remasking the masked string should yield a no password comment masked_masked = mask_connection_info(masked_str) _, masked_password_info = masked_masked.split("; ", 1) assert masked_password_info == "no password"