diff --git a/src/node.py b/src/node.py index 83b9b079..148cae89 100644 --- a/src/node.py +++ b/src/node.py @@ -161,6 +161,7 @@ class PostgresNode(object): _C_PM_PID__IS_NOT_DETECTED = -1 _name: typing.Optional[str] + _host: str _port: typing.Optional[int] _bin_dir: str _should_free_port: bool @@ -168,14 +169,17 @@ class PostgresNode(object): _port_manager: typing.Optional[PortManager] _manually_started_pm_pid: typing.Optional[int] - def __init__(self, - name=None, - base_dir=None, - port: typing.Optional[int] = None, - bin_dir: typing.Optional[str] = None, - prefix=None, - os_ops: typing.Optional[OsOperations] = None, - port_manager: typing.Optional[PortManager] = None): + def __init__( + self, + name=None, + base_dir=None, + port: typing.Optional[int] = None, + bin_dir: typing.Optional[str] = None, + prefix=None, + os_ops: typing.Optional[OsOperations] = None, + port_manager: typing.Optional[PortManager] = None, + host: typing.Optional[str] = None, + ): """ PostgresNode constructor. @@ -186,11 +190,13 @@ def __init__(self, bin_dir: path to node's binary directory. os_ops: None or correct OS operation object. port_manager: None or correct port manager object. + host: None or valid address of node host. """ assert port is None or type(port) is int assert bin_dir is None or type(bin_dir) is str assert os_ops is None or isinstance(os_ops, OsOperations) assert port_manager is None or isinstance(port_manager, PortManager) + assert host is None or type(host) is str # private if os_ops is None: @@ -219,6 +225,16 @@ def __init__(self, # basic self._name = name or generate_app_name() + if host is not None: + assert type(host) is str + self._host = host + else: + self._host = self._os_ops.host + assert type(self._host) is str + + if self._host == "": + raise RuntimeError("PostgresNode host is empty.") + if port is not None: assert type(port) is int assert port_manager is None @@ -317,6 +333,7 @@ def clone_with_new_name_and_base_dir(self, name: str, base_dir: str): assert isinstance(self._port_manager, PortManager) assert self._os_ops is not None assert isinstance(self._os_ops, OsOperations) + assert type(self._host) is str node = PostgresNode( name=name, @@ -324,7 +341,9 @@ def clone_with_new_name_and_base_dir(self, name: str, base_dir: str): bin_dir=self._bin_dir, prefix=self._prefix, os_ops=self._os_ops, - port_manager=self._port_manager) + port_manager=self._port_manager, + host=self._host, + ) return node @@ -348,9 +367,9 @@ def name(self) -> str: @property def host(self) -> str: - assert self._os_ops is not None - assert isinstance(self._os_ops, OsOperations) - return self._os_ops.host + assert self._host is not None + assert type(self._host) is str + return self._host @property def port(self) -> int: @@ -467,7 +486,7 @@ def source_walsender(self): assert type(self.master) is PostgresNode # master should be on the same host - assert self.master.host == self.host + assert self.master.host == self._host with self.master.connect() as con: for row in con.execute(sql, self.name): @@ -838,7 +857,7 @@ def get_auth_method(t): self.append_conf(fsync=fsync, max_worker_processes=MAX_WORKER_PROCESSES, log_statement=log_statement, - listen_addresses=self.host, + listen_addresses=self._host, port=self.port) # yapf:disable # common replication settings @@ -1453,7 +1472,7 @@ def _psql( raise Exception("Input data must be None or bytes.") if host is None: - host = self.host + host = self._host if port is None: port = self.port @@ -1580,7 +1599,7 @@ def tmpfile(): _params = [ self._get_bin_path("pg_dump"), "-p", str(self.port), - "-h", self.host, + "-h", self._host, "-f", filename, "-U", username or self._os_ops.username, "-d", dbname or default_dbname(), @@ -1612,7 +1631,7 @@ def restore(self, filename, dbname=None, username=None): _params = [ self._get_bin_path("pg_restore"), "-p", str(self.port), - "-h", self.host, + "-h", self._host, "-U", username, "-d", dbname, filename @@ -1888,7 +1907,7 @@ def pgbench(self, _params = [ self._get_bin_path("pgbench"), "-p", str(self.port), - "-h", self.host, + "-h", self._host, "-U", username or self._os_ops.username ] + options # yapf: disable @@ -1961,7 +1980,7 @@ def pgbench_run(self, dbname=None, username=None, options=[], **kwargs): _params = [ self._get_bin_path("pgbench"), "-p", str(self.port), - "-h", self.host, + "-h", self._host, "-U", username or self._os_ops.username ] + options # yapf: disable diff --git a/tests/test_testgres_common.py b/tests/test_testgres_common.py index e48e0a8a..855d24c8 100644 --- a/tests/test_testgres_common.py +++ b/tests/test_testgres_common.py @@ -132,7 +132,41 @@ def test_version_management(self, node_svc: PostgresNodeService): assert (isinstance(node.version, PgVer)) assert (node.version == PgVer(version)) + def test_node_constructor__host(self): + C_HOST = "AbCdE" + + unique_id = uuid.uuid4().hex + + with PostgresNode(host=C_HOST) as node: + assert node._host == C_HOST + assert node.host == C_HOST + assert isinstance(node.os_ops, OsOperations) + + tmpdir = node.os_ops.get_tempdir() + nodedir2 = node.os_ops.build_path(tmpdir, "node2--" + unique_id) + + C_NODE2_NAME = "node2" + + with node.clone_with_new_name_and_base_dir( + name=C_NODE2_NAME, + base_dir=nodedir2, + ) as node2: + assert node2 is not None + assert node2 is not node + + assert node2._host == C_HOST + assert node2.host == C_HOST + + assert node2._name == C_NODE2_NAME + assert node2._base_dir == nodedir2 + assert node2._port != node._port + assert node2._os_ops is node._os_ops + assert node2._port_manager is node._port_manager + return + def test_node_repr(self, node_svc: PostgresNodeService): + assert isinstance(node_svc, PostgresNodeService) + with __class__.helper__get_node(node_svc).init() as node: pattern = r"PostgresNode\(name='.+', port=.+, base_dir='.+'\)" assert re.match(pattern, str(node)) is not None