21
21
from ops import BlockedStatus
22
22
from pysyncobj .utility import TcpUtility , UtilityException
23
23
from tenacity import (
24
- AttemptManager ,
25
24
RetryError ,
26
25
Retrying ,
27
26
retry ,
@@ -233,11 +232,12 @@ def get_member_ip(self, member_name: str) -> str:
233
232
IP address of the cluster member.
234
233
"""
235
234
# Request info from cluster endpoint (which returns all members of the cluster).
236
- for attempt in Retrying (stop = stop_after_attempt (2 * len (self .peers_ips ) + 1 )):
235
+ attempts = 2 * len (self .peers_ips ) + 2
236
+ urls = self ._get_alternative_patroni_url ()
237
+ for attempt in Retrying (stop = stop_after_attempt (attempts )):
237
238
with attempt :
238
- url = self ._get_alternative_patroni_url (attempt )
239
239
cluster_status = requests .get (
240
- f"{ url } /{ PATRONI_CLUSTER_STATUS_ENDPOINT } " ,
240
+ f"{ next ( urls ) } /{ PATRONI_CLUSTER_STATUS_ENDPOINT } " ,
241
241
verify = self .verify ,
242
242
timeout = API_REQUEST_TIMEOUT ,
243
243
auth = self ._patroni_auth ,
@@ -257,11 +257,12 @@ def get_member_status(self, member_name: str) -> str:
257
257
couldn't be retrieved yet.
258
258
"""
259
259
# Request info from cluster endpoint (which returns all members of the cluster).
260
- for attempt in Retrying (stop = stop_after_attempt (2 * len (self .peers_ips ) + 1 )):
260
+ attempts = 2 * len (self .peers_ips ) + 2
261
+ urls = self ._get_alternative_patroni_url ()
262
+ for attempt in Retrying (stop = stop_after_attempt (attempts )):
261
263
with attempt :
262
- url = self ._get_alternative_patroni_url (attempt )
263
264
cluster_status = requests .get (
264
- f"{ url } /{ PATRONI_CLUSTER_STATUS_ENDPOINT } " ,
265
+ f"{ next ( urls ) } /{ PATRONI_CLUSTER_STATUS_ENDPOINT } " ,
265
266
verify = self .verify ,
266
267
timeout = API_REQUEST_TIMEOUT ,
267
268
auth = self ._patroni_auth ,
@@ -284,11 +285,15 @@ def get_primary(
284
285
primary pod or unit name.
285
286
"""
286
287
# Request info from cluster endpoint (which returns all members of the cluster).
287
- for attempt in Retrying (stop = stop_after_attempt (2 * len (self .peers_ips ) + 1 )):
288
+ if alternative_endpoints :
289
+ attempts = 2 * len (alternative_endpoints ) + 2
290
+ else :
291
+ attempts = 2 * len (self .peers_ips ) + 2
292
+ urls = self ._get_alternative_patroni_url (alternative_endpoints )
293
+ for attempt in Retrying (stop = stop_after_attempt (attempts )):
288
294
with attempt :
289
- url = self ._get_alternative_patroni_url (attempt , alternative_endpoints )
290
295
cluster_status = requests .get (
291
- f"{ url } /{ PATRONI_CLUSTER_STATUS_ENDPOINT } " ,
296
+ f"{ next ( urls ) } /{ PATRONI_CLUSTER_STATUS_ENDPOINT } " ,
292
297
verify = self .verify ,
293
298
timeout = API_REQUEST_TIMEOUT ,
294
299
auth = self ._patroni_auth ,
@@ -314,11 +319,12 @@ def get_standby_leader(
314
319
standby leader pod or unit name.
315
320
"""
316
321
# Request info from cluster endpoint (which returns all members of the cluster).
317
- for attempt in Retrying (stop = stop_after_attempt (2 * len (self .peers_ips ) + 1 )):
322
+ attempts = 2 * len (self .peers_ips ) + 2
323
+ urls = self ._get_alternative_patroni_url ()
324
+ for attempt in Retrying (stop = stop_after_attempt (attempts )):
318
325
with attempt :
319
- url = self ._get_alternative_patroni_url (attempt )
320
326
cluster_status = requests .get (
321
- f"{ url } /{ PATRONI_CLUSTER_STATUS_ENDPOINT } " ,
327
+ f"{ next ( urls ) } /{ PATRONI_CLUSTER_STATUS_ENDPOINT } " ,
322
328
verify = self .verify ,
323
329
timeout = API_REQUEST_TIMEOUT ,
324
330
auth = self ._patroni_auth ,
@@ -338,9 +344,13 @@ def get_sync_standby_names(self) -> list[str]:
338
344
"""Get the list of sync standby unit names."""
339
345
sync_standbys = []
340
346
# Request info from cluster endpoint (which returns all members of the cluster).
341
- for attempt in Retrying (stop = stop_after_attempt (2 * len (self .peers_ips ) + 1 )):
347
+ attempts = 2 * len (self .peers_ips ) + 2
348
+ for attempt , url in zip (
349
+ Retrying (stop = stop_after_attempt (attempts )),
350
+ self ._get_alternative_patroni_url (),
351
+ strict = True ,
352
+ ):
342
353
with attempt :
343
- url = self ._get_alternative_patroni_url (attempt )
344
354
r = requests .get (
345
355
f"{ url } /cluster" ,
346
356
verify = self .verify ,
@@ -352,33 +362,26 @@ def get_sync_standby_names(self) -> list[str]:
352
362
sync_standbys .append ("/" .join (member ["name" ].rsplit ("-" , 1 )))
353
363
return sync_standbys
354
364
355
- def _get_alternative_patroni_url (
356
- self , attempt : AttemptManager , alternative_endpoints : list [str ] | None = None
357
- ) -> str :
365
+ def _get_alternative_patroni_url (self , alternative_endpoints : list [str ] | None = None ) -> str :
358
366
"""Get an alternative REST API URL from another member each time.
359
367
360
368
When the Patroni process is not running in the current unit it's needed
361
369
to use a URL from another cluster member REST API to do some operations.
362
370
"""
363
- if alternative_endpoints is not None :
364
- return self ._patroni_url .replace (
365
- self .unit_ip , alternative_endpoints [attempt .retry_state .attempt_number - 1 ]
366
- )
367
- attempt_number = attempt .retry_state .attempt_number
368
- if attempt_number > 1 :
369
- url = self ._patroni_url
370
- # Build the URL using http and later using https for each peer.
371
- if (attempt_number - 1 ) <= len (self .peers_ips ):
372
- url = url .replace ("https://" , "http://" )
373
- unit_number = attempt_number - 2
374
- else :
375
- url = url .replace ("http://" , "https://" )
376
- unit_number = attempt_number - 2 - len (self .peers_ips )
377
- other_unit_ip = list (self .peers_ips )[unit_number ]
378
- url = url .replace (self .unit_ip , other_unit_ip )
371
+ if not alternative_endpoints :
372
+ alternative_endpoints = list (self .peers_ips )
373
+ urls = [self ._patroni_url ]
374
+ urls += [
375
+ self ._patroni_url .replace (self .unit_ip , endpoint ) for endpoint in alternative_endpoints
376
+ ]
377
+ if self .tls_enabled :
378
+ default_schema = "https"
379
+ new_schema = "http"
379
380
else :
380
- url = self ._patroni_url
381
- return url
381
+ default_schema = "http"
382
+ new_schema = "https"
383
+ urls += [url .replace (default_schema , new_schema ) for url in urls ]
384
+ yield from urls
382
385
383
386
def are_all_members_ready (self ) -> bool :
384
387
"""Check if all members are correctly running Patroni and PostgreSQL.
0 commit comments