# patroni.postgresql.config module

class patroni.postgresql.config.ConfigHandler(postgresql: Postgresql, config: Dict[str, Any])

  Bases: `object`

  CMDLINE_OPTIONS = <CaseInsensitiveDict{'listen_addresses': (None, <function _false_validator>, 90100), 'port': (None, <function _false_validator>, 90100), 'cluster_name': (None, <function _false_validator>, 90500), 'wal_level': ('hot_standby', <patroni.validator.EnumValidator object>, 90100), 'hot_standby': ('on', <function _bool_is_true_validator>, 90100), 'max_connections': (100, <patroni.validator.IntValidator object>, 90100), 'max_wal_senders': (10, <patroni.validator.IntValidator object>, 90100), 'wal_keep_segments': (8, <patroni.validator.IntValidator object>, 90100), 'wal_keep_size': ('128MB', <patroni.validator.IntValidator object>, 130000), 'max_prepared_transactions': (0, <patroni.validator.IntValidator object>, 90100), 'max_locks_per_transaction': (64, <patroni.validator.IntValidator object>, 90100), 'track_commit_timestamp': ('off', <function _bool_validator>, 90500), 'max_replication_slots': (10, <patroni.validator.IntValidator object>, 90400), 'max_worker_processes': (8, <patroni.validator.IntValidator object>, 90400), 'wal_log_hints': ('on', <function _bool_validator>, 90400)}>
  _RECOVERY_PARAMETERS = <CaseInsensitiveSet('archive_cleanup_command', 'pause_at_recovery_target', 'primary_conninfo', 'primary_slot_name', 'promote_trigger_file', 'recovery_end_command', 'recovery_min_apply_delay', 'recovery_target', 'recovery_target_action', 'recovery_target_inclusive', 'recovery_target_lsn', 'recovery_target_name', 'recovery_target_time', 'recovery_target_timeline', 'recovery_target_xid', 'restore_command', 'standby_mode', 'trigger_file')>
  __init__(postgresql: Postgresql, config: Dict[str, Any]) → None
  _adjust_recovery_parameters() → None
  _check_passfile(passfile: str, wanted_primary_conninfo: Dict[str, Any]) → bool
  _check_primary_conninfo(primary_conninfo: Dict[str, Any], wanted_primary_conninfo: Dict[str, Any]) → bool
  property _configuration_to_save: List[str]
  _get_pg_settings(names: Collection[str]) → Dict[Any, Tuple[Any, ...]]
  _get_tcp_local_address() → str
  static _get_unix_local_address(unix_socket_directories: str) → str
  static _handle_wal_buffers(old_values: Dict[Any, Tuple[Any, ...]], changes: CaseInsensitiveDict) → None
  static _pgpass_content(record: Dict[str, Any]) → str | None

    Generate content of pgpassfile based on connection parameters.

    Note

    In case if `host` is a comma separated string we generate one line per host.

    Parameters:

      record – `dict` object with connection parameters.

    Returns:

      a string with generated content of pgpassfile or `None` if there is no `password`.

  _read_recovery_params() → Tuple[CaseInsensitiveDict | None, bool]

    Read current recovery parameters values.

    Note

    We query Postgres only if we detected that Postgresql was restarted or when at least one of the following files was updated:

    > - `postgresql.conf`;

    > - `postgresql.auto.conf`;

    > - `passfile` that is used in the `primary_conninfo`.

    Returns:

      a tuple with two elements:

      - `CaseInsensitiveDict` object with current values of recovery parameters, or `None` if no configuration files were updated;

      - `True` if new values of recovery parameters were queried, `False` otherwise.

  _read_recovery_params_pre_v12() → Tuple[CaseInsensitiveDict | None, bool]
  property _recovery_parameters_to_compare: CaseInsensitiveSet
  static _remove_file_if_exists(name: str) → None
  _sanitize_auto_conf() → None
  property _triggerfile_wrong_name: str
  _write_recovery_params(fd: ConfigWriter, recovery_params: CaseInsensitiveDict) → None
  append_pg_hba(config: List[str]) → bool
  build_recovery_params(member: Leader | Member | None) → CaseInsensitiveDict
  check_directories() → None
  check_recovery_conf(member: Leader | Member | None) → Tuple[bool, bool]

    Returns a tuple. The first boolean element indicates that recovery params don’t match and the second is set to True if the restart is required in order to apply new values

  property config_dir: str
  config_writer(filename: str) → Generator[ConfigWriter, None, None]

    Create `ConfigWriter` object and set permissions on a filename.

    Parameters:

      filename – path to a config file.

    Yields:

      `ConfigWriter` object.

  property effective_configuration: CaseInsensitiveDict

    It might happen that the current value of one (or more) below parameters stored in the controldata is higher than the value stored in the global cluster configuration.

    Example: max_connections in global configuration is 100, but in controldata Current max_connections setting: 200. If we try to start postgres with max_connections=100, it will immediately exit. As a workaround we will start it with the values from controldata and set pending_restart to true as an indicator that current values of parameters are not matching expectations.

  format_dsn(params: Dict[str, Any]) → str

    Format connection string from connection parameters.

    Note

    only parameters from the below list are considered and values are escaped.

    Parameters:

      params – `dict` object with connection parameters.

    Returns:

      a connection string in a format “key1=value2 key2=value2”

  get(key: str, default: Any | None = None) → Any | None
  get_server_parameters(config: Dict[str, Any]) → CaseInsensitiveDict
  property hba_file: str | None
  property ident_file: str | None
  load_current_server_parameters() → None

    Read GUC’s values from `pg_settings` when Patroni is joining the the postgres that is already running.

  property pg_hba_conf: str
  property pg_version: int

    Return current postgres version.

    If instance is running, try to get version from the server. If it is not possible, get minor version from the binary. However, we can only use `postgres --version` output if major version there equals to the one in data directory. If it is not the case, use major version from the `PG_VERSION` file. If `PG_VERSION` file is missing, inaccessible, or contains invalid value, use minor version from the binary.

    Returns:

      integer representation of the current postgres version.

  property postgresql_conf: str
  primary_conninfo_params(member: Leader | Member | None) → Dict[str, Any] | None
  recovery_conf_exists() → bool
  reload_config(config: Dict[str, Any], sighup: bool = False) → None
  remove_recovery_conf() → None
  replace_pg_hba() → bool | None

    Replace pg_hba.conf content in the PGDATA if hba_file is not defined in the postgresql.parameters and pg_hba is defined in postgresql configuration section.

    Returns:

      True if pg_hba.conf was rewritten.

  replace_pg_ident() → bool | None

    Replace pg_ident.conf content in the PGDATA if ident_file is not defined in the postgresql.parameters and pg_ident is defined in the postgresql section.

    Returns:

      True if pg_ident.conf was rewritten.

  property replication: Dict[str, Any]
  resolve_connection_addresses() → None

    Calculates and sets local and remote connection urls and options.

    This method sets:

      - `Postgresql.connection_string` attribute, which is later written to the member key in DCS as `conn_url`.

      - `ConfigHandler.local_replication_address` attribute, which is used for replication connections to local postgres.

      - `ConnectionPool.conn_kwargs` attribute, which is used for superuser connections to local postgres.

    Note

    If there is a valid directory in `postgresql.parameters.unix_socket_directories` in the Patroni configuration and `postgresql.use_unix_socket` and/or `postgresql.use_unix_socket_repl` are set to `True`, we respectively use unix sockets for superuser and replication connections to local postgres.

    If there is a requirement to use unix sockets, but nothing is set in the `postgresql.parameters.unix_socket_directories`, we omit a `host` in connection parameters relying on the ability of `libpq` to connect via some default unix socket directory.

    If unix sockets are not requested we “switch” to TCP, preferring to use `localhost` if it is possible to deduce that Postgres is listening on a local interface address.

    Otherwise we just used the first address specified in the `listen_addresses` GUC.

  restore_command() → str | None
  restore_configuration_files() → None

    restore a previously saved postgresql.conf

  property rewind_credentials: Dict[str, Any]
  save_configuration_files(check_custom_bootstrap: bool = False) → bool

    copy postgresql.conf to postgresql.conf.backup to be able to retrieve configuration files - originally stored as symlinks, those are normally skipped by pg_basebackup - in case of WAL-E basebackup (see http://comments.gmane.org/gmane.comp.db.postgresql.wal-e/239)

  set_file_permissions(filename: str) → None

    Set permissions of file filename according to the expected permissions.

    Note

    Use original umask if the file is not under PGDATA, use PGDATA permissions otherwise.

    Parameters:

      filename – path to a file which permissions might need to be adjusted.

  set_synchronous_standby_names(value: str | None) → bool | None

    Updates synchronous_standby_names and reloads if necessary. :returns: True if value was updated.

  setup_server_parameters() → None
  property superuser: Dict[str, Any]
  property synchronous_standby_names: str | None

    Get `synchronous_standby_names` value configured by the user.

    Returns:

      value of `synchronous_standby_names` in the Patroni configuration, if any, otherwise `None`.

  property triggerfile_good_name: str
  try_to_create_dir(d: str, msg: str) → None
  write_pgpass(record: Dict[str, Any]) → Dict[str, str]

    Maybe creates `_passfile` based on connection parameters.

    Parameters:

      record – `dict` object with connection parameters.

    Returns:

      a copy of environment variables, that will include `PGPASSFILE` in case if the file was written.

  write_postgresql_conf(configuration: CaseInsensitiveDict | None = None) → None
  write_recovery_conf(recovery_params: CaseInsensitiveDict) → None

class patroni.postgresql.config.ConfigWriter(filename: str)

  Bases: `object`

  __init__(filename: str) → None
  static escape(value: Any) → str
  write_param(param: str, value: Any) → None
  writeline(line: str) → None
  writelines(lines: List[str | None]) → None

patroni.postgresql.config._bool_is_true_validator(value: Any) → bool

patroni.postgresql.config._bool_validator(value: Any) → bool

patroni.postgresql.config._conninfo_dsn_parse(dsn: str) → Dict[str, str] | None

      >>> r = _conninfo_dsn_parse(" host = 'host' dbname = db\\ name requiressl=1 ")
      >>> r == {'dbname': 'db name', 'host': 'host', 'requiressl': '1'}
      True
      >>> _conninfo_dsn_parse('requiressl = 0\\') == {'requiressl': '0'}
      True
      >>> _conninfo_dsn_parse("host=a foo = '") is None
      True
      >>> _conninfo_dsn_parse("host=a foo = ") is None
      True
      >>> _conninfo_dsn_parse("1") is None
      True

patroni.postgresql.config._conninfo_parse(value: str) → Dict[str, str] | None

  Very simple equivalent of psycopg2.extensions.parse_dsn introduced in 2.7.0. Exists just for compatibility with 2.5.4+.

      >>> r = _conninfo_parse('postgresql://foo/postgres')
      >>> r == {'dbname': 'postgres', 'host': 'foo'}
      True
      >>> r = _conninfo_parse(" host = 'host' dbname = db\\ name requiressl=1 ")
      >>> r == {'dbname': 'db name', 'host': 'host', 'sslmode': 'require'}
      True
      >>> _conninfo_parse('requiressl = 0\\') == {'sslmode': 'prefer'}
      True

patroni.postgresql.config._conninfo_uri_parse(dsn: str) → Dict[str, str]

      >>> r = _conninfo_uri_parse('postgresql://u%2Fse:pass@:%2f123/db%2Fsdf?application_name=mya%2Fpp&ssl=true')
      >>> r == {'application_name': 'mya/pp', 'dbname': 'db/sdf', 'sslmode': 'require',              'password': 'pass', 'port': '/123', 'user': 'u/se'}
      True
      >>> r = _conninfo_uri_parse('postgresql://u%2Fse:pass@[::1]/db%2Fsdf?application_name=mya%2Fpp&ssl=true')
      >>> r == {'application_name': 'mya/pp', 'dbname': 'db/sdf', 'host': '::1', 'sslmode': 'require',              'password': 'pass', 'user': 'u/se'}
      True

patroni.postgresql.config._false_validator(value: Any) → bool

patroni.postgresql.config.get_param_diff(old_value: Any, new_value: Any, vartype: str | None = None, unit: str | None = None) → Dict[str, str]

  Get a dictionary representing a single PG parameter’s value diff.

  Parameters:

    - old_value – current `str` parameter value.

    - new_value – `str` value of the parameter after a restart.

    - vartype – the target type to parse old/new_value. See `vartype` argument of `maybe_convert_from_base_unit()`.

    - unit – unit of old/new_value. See `base_unit` argument of `maybe_convert_from_base_unit()`.

  Returns:

    a `dict` object that contains two keys: `old_value` and `new_value` with their values casted to `str` and converted from base units (if possible).

patroni.postgresql.config.mtime(filename: str) → float | None

patroni.postgresql.config.parse_dsn(value: str) → Dict[str, str] | None

  Compatibility layer on top of function from psycopg2/psycopg3, which parses connection strings. In this function sets the sslmode, ‘gssencmode’, and channel_binding to prefer and sslnegotiation to postgres if they are not present in the connection string. This is necessary to simplify comparison of the old and the new values.

      >>> r = parse_dsn('postgresql://foo/postgres')
      >>> r == {'dbname': 'postgres', 'host': 'foo', 'sslmode': 'prefer', 'gssencmode': 'prefer',              'channel_binding': 'prefer', 'sslnegotiation': 'postgres'}
      True
      >>> r = parse_dsn(" host = 'host' dbname = db\\ name requiressl=1 ")
      >>> r == {'dbname': 'db name', 'host': 'host', 'sslmode': 'require',              'gssencmode': 'prefer', 'channel_binding': 'prefer', 'sslnegotiation': 'postgres'}
      True
      >>> parse_dsn('requiressl = 0\\') == {'sslmode': 'prefer', 'gssencmode': 'prefer',                                            'channel_binding': 'prefer', 'sslnegotiation': 'postgres'}
      True
      >>> parse_dsn('foo=bar') == {'foo': 'bar', 'sslmode': 'prefer', 'gssencmode': 'prefer',                                 'channel_binding': 'prefer', 'sslnegotiation': 'postgres'}
      True

patroni.postgresql.config.read_param_value(value: str) → Tuple[None, None] | Tuple[str, int]

patroni.postgresql.config.read_recovery_param_value(value: str) → str | None

      >>> read_recovery_param_value('') is None
      True
      >>> read_recovery_param_value("'") is None
      True
      >>> read_recovery_param_value("''a") is None
      True
      >>> read_recovery_param_value('a b') is None
      True
      >>> read_recovery_param_value("'''") is None
      True
      >>> read_recovery_param_value("'\\") is None
      True
      >>> read_recovery_param_value("'a' s#") is None
      True
      >>> read_recovery_param_value("'\\'''' #a")
      "''"
      >>> read_recovery_param_value('asd')
      'asd'

patroni.postgresql.config.strip_comment(value: str) → str