Skip to content

Commit d243e49

Browse files
committed
generate application name if asked to
1 parent 2ecd3a8 commit d243e49

File tree

6 files changed

+76
-32
lines changed

6 files changed

+76
-32
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ import logging
5454
logging.basicConfig(filename='/tmp/testgres.log')
5555

5656
# create two different nodes with logging
57-
node1 = testgres.get_new_node('node1', use_logging=True).init().start()
58-
node2 = testgres.get_new_node('node2', use_logging=True).init().start()
57+
node1 = testgres.get_new_node(use_logging=True).init().start()
58+
node2 = testgres.get_new_node(use_logging=True).init().start()
5959

6060
# execute a few queries
6161
node1.execute('postgres', 'select 1')
@@ -87,7 +87,7 @@ or
8787
with testgres.get_new_node('master', '/path/to/DB') as node:
8888
```
8989

90-
where `master` is a node's name, not a DB's name. Name matters if you're testing something like replication.
90+
where `master` is a node's application name. Name matters if you're testing something like replication.
9191
Function `get_new_node()` only creates directory structure in specified directory (or somewhere in '/tmp' if
9292
we did not specify base directory) for cluster. After that, we have to initialize the PostgreSQL cluster:
9393

testgres/api.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
edit configuration files, start/stop cluster, execute queries. The
88
typical flow may look like:
99
10-
with get_new_node('test') as node:
10+
with get_new_node() as node:
1111
node.init()
1212
node.start()
1313
result = node.psql('postgres', 'SELECT 1')
@@ -16,10 +16,10 @@
1616
1717
Or:
1818
19-
with get_new_node('node1') as node1:
19+
with get_new_node() as node1:
2020
node1.init().start()
2121
with node1.backup() as backup:
22-
with backup.spawn_primary('node2') as node2:
22+
with backup.spawn_primary() as node2:
2323
res = node2.start().execute('postgres', 'select 2')
2424
print(res)
2525
@@ -29,12 +29,12 @@
2929
from .node import PostgresNode
3030

3131

32-
def get_new_node(name, base_dir=None, use_logging=False):
32+
def get_new_node(name=None, base_dir=None, use_logging=False):
3333
"""
3434
Create a new node (select port automatically).
3535
3636
Args:
37-
name: node's name.
37+
name: node's application name.
3838
base_dir: path to node's data directory.
3939
use_logging: enable python logging.
4040

testgres/backup.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -114,28 +114,27 @@ def _prepare_dir(self, destroy):
114114
# Return path to new node
115115
return dest_base_dir
116116

117-
def spawn_primary(self, name, destroy=True, use_logging=False):
117+
def spawn_primary(self, name=None, destroy=True, use_logging=False):
118118
"""
119119
Create a primary node from a backup.
120120
121121
Args:
122-
name: name for a new node.
122+
name: primary's application name.
123123
destroy: should we convert this backup into a node?
124124
use_logging: enable python logging.
125125
126126
Returns:
127127
New instance of PostgresNode.
128128
"""
129129

130+
# Prepare a data directory for this node
130131
base_dir = self._prepare_dir(destroy)
131132

132133
# Build a new PostgresNode
133134
from .node import PostgresNode
134-
node = PostgresNode(
135-
name=name,
136-
base_dir=base_dir,
137-
master=self.original_node,
138-
use_logging=use_logging)
135+
node = PostgresNode(name=name,
136+
base_dir=base_dir,
137+
use_logging=use_logging)
139138

140139
# New nodes should always remove dir tree
141140
node._should_rm_dirs = True
@@ -145,22 +144,27 @@ def spawn_primary(self, name, destroy=True, use_logging=False):
145144

146145
return node
147146

148-
def spawn_replica(self, name, destroy=True, use_logging=False):
147+
def spawn_replica(self, name=None, destroy=True, use_logging=False):
149148
"""
150149
Create a replica of the original node from a backup.
151150
152151
Args:
153-
name: name for a new node.
152+
name: replica's application name.
154153
destroy: should we convert this backup into a node?
155154
use_logging: enable python logging.
156155
157156
Returns:
158157
New instance of PostgresNode.
159158
"""
160159

161-
node = self.spawn_primary(name, destroy, use_logging=use_logging)
162-
node._create_recovery_conf(username=self.username,
163-
master=self.original_node)
160+
# Build a new PostgresNode
161+
node = self.spawn_primary(name=name,
162+
destroy=destroy,
163+
use_logging=use_logging)
164+
165+
# Assign it a master and a recovery file (private magic)
166+
node._assign_master(self.original_node)
167+
node._create_recovery_conf(username=self.username)
164168

165169
return node
166170

testgres/node.py

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
reserve_port as _reserve_port, \
4242
release_port as _release_port, \
4343
default_username as _default_username, \
44+
generate_app_name as _generate_app_name, \
4445
execute_utility as _execute_utility
4546

4647

@@ -60,18 +61,23 @@ def __bool__(self):
6061

6162

6263
class PostgresNode(object):
63-
def __init__(self,
64-
name,
65-
port=None,
66-
base_dir=None,
67-
use_logging=False,
68-
master=None):
64+
def __init__(self, name=None, port=None, base_dir=None, use_logging=False):
65+
"""
66+
Create a new node manually.
67+
68+
Args:
69+
name: node's application name.
70+
port: port to accept connections.
71+
base_dir: path to node's data directory.
72+
use_logging: enable python logging.
73+
"""
74+
6975
global bound_ports
7076

7177
# public
72-
self.master = master
73-
self.name = name
78+
self.master = None
7479
self.host = '127.0.0.1'
80+
self.name = name or _generate_app_name()
7581
self.port = port or _reserve_port()
7682
self.base_dir = base_dir
7783

@@ -112,7 +118,14 @@ def utils_log_name(self):
112118
def pg_log_name(self):
113119
return os.path.join(self.logs_dir, _PG_LOG_FILE)
114120

115-
def _create_recovery_conf(self, username, master):
121+
def _assign_master(self, master):
122+
# now this node has a master
123+
self.master = master
124+
125+
def _create_recovery_conf(self, username):
126+
# fetch master of this node
127+
master = self.master
128+
116129
# yapf: disable
117130
conninfo = (
118131
u"application_name={} "
@@ -785,22 +798,25 @@ def backup(self, username=None, xlog_method=_DEFAULT_XLOG_METHOD):
785798
return NodeBackup(node=self, username=username, xlog_method=xlog_method)
786799

787800
def replicate(self,
788-
name,
801+
name=None,
789802
username=None,
790803
xlog_method=_DEFAULT_XLOG_METHOD,
791804
use_logging=False):
792805
"""
793806
Create a binary replica of this node.
794807
795808
Args:
796-
name: replica's name.
809+
name: replica's application name.
797810
username: database user name.
798811
xlog_method: a method for collecting the logs ('fetch' | 'stream').
799812
use_logging: enable python logging.
800813
"""
801814

815+
# transform backup into a replica
802816
backup = self.backup(username=username, xlog_method=xlog_method)
803-
return backup.spawn_replica(name=name, use_logging=use_logging)
817+
return backup.spawn_replica(name=name,
818+
destroy=True,
819+
use_logging=use_logging)
804820

805821
def catchup(self, dbname='postgres', username=None):
806822
"""

testgres/utils.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ def default_username():
4747
return pwd.getpwuid(os.getuid())[0]
4848

4949

50+
def generate_app_name():
51+
"""
52+
Generate a new application name for node.
53+
"""
54+
55+
import uuid
56+
return ''.join(['testgres-', str(uuid.uuid4())])
57+
58+
5059
def execute_utility(args, logfile):
5160
"""
5261
Execute utility (pg_ctl, pg_dump etc).

tests/test_simple.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,21 @@ def test_unix_sockets(self):
602602
r.execute('postgres', 'select 1')
603603
r.safe_psql('postgres', 'select 1')
604604

605+
def test_auto_name(self):
606+
with get_new_node().init(allow_streaming=True).start() as m:
607+
with m.replicate().start() as r:
608+
609+
# check that nodes are running
610+
self.assertTrue(m.status())
611+
self.assertTrue(r.status())
612+
613+
# check their names
614+
self.assertIsNotNone(m.name)
615+
self.assertIsNotNone(r.name)
616+
self.assertNotEqual(m.name, r.name)
617+
self.assertTrue('testgres' in m.name)
618+
self.assertTrue('testgres' in r.name)
619+
605620
def test_isolation_levels(self):
606621
with get_new_node('node').init().start() as node:
607622
with node.connect() as con:

0 commit comments

Comments
 (0)