diff --git a/patroni/ctl.py b/patroni/ctl.py index fabb4077..6b2d8511 100644 --- a/patroni/ctl.py +++ b/patroni/ctl.py @@ -46,6 +46,7 @@ try: except ImportError: # pragma: no cover from cdiff import markup_to_pager, PatchStream # pyright: ignore [reportMissingModuleSource] +from .config import get_global_config from .dcs import get_dcs as _get_dcs, AbstractDCS, Cluster, Member from .exceptions import PatroniException from .postgresql.misc import postgres_version_to_int @@ -1011,7 +1012,6 @@ def reload(obj: Dict[str, Any], cluster_name: str, member_names: List[str], if r.status == 200: click.echo('No changes to apply on member {0}'.format(member.name)) elif r.status == 202: - from patroni.config import get_global_config config = get_global_config(cluster) click.echo('Reload request received for member {0} and will be processed within {1} seconds'.format( member.name, config.get('loop_wait') or dcs.loop_wait) @@ -1093,7 +1093,6 @@ def restart(obj: Dict[str, Any], cluster_name: str, group: Optional[int], member content['postgres_version'] = version if scheduled_at: - from patroni.config import get_global_config if get_global_config(cluster).is_paused: raise PatroniCtlException("Can't schedule restart in the paused state") content['schedule'] = scheduled_at.isoformat() @@ -1221,6 +1220,8 @@ def _do_failover_or_switchover(obj: Dict[str, Any], action: str, cluster_name: s dcs = get_dcs(obj, cluster_name, group) cluster = dcs.get_cluster() + global_config = get_global_config(cluster) + # leader has to be be defined for switchover only if action == 'switchover': if cluster.leader is None or not cluster.leader.name: @@ -1230,8 +1231,7 @@ def _do_failover_or_switchover(obj: Dict[str, Any], action: str, cluster_name: s if force: leader = cluster.leader.name else: - from patroni.config import get_global_config - prompt = 'Standby Leader' if get_global_config(cluster).is_standby_cluster else 'Primary' + prompt = 'Standby Leader' if global_config.is_standby_cluster else 'Primary' leader = click.prompt(prompt, type=str, default=(cluster.leader and cluster.leader.name)) if cluster.leader.name != leader: @@ -1251,7 +1251,7 @@ def _do_failover_or_switchover(obj: Dict[str, Any], action: str, cluster_name: s if action == 'failover' and not candidate: raise PatroniCtlException('Failover could be performed only to a specific candidate') - if leader and candidate == leader: + if candidate == leader: raise PatroniCtlException(action.title() + ' target and source are the same.') if candidate and candidate not in candidate_names: @@ -1259,8 +1259,7 @@ def _do_failover_or_switchover(obj: Dict[str, Any], action: str, cluster_name: s f'Member {candidate} does not exist in cluster {cluster_name} or is tagged as nofailover') if not force and action == 'failover': - from patroni.config import get_global_config - if get_global_config(cluster).is_synchronous_mode and not cluster.sync.is_empty\ + if global_config.is_synchronous_mode and not cluster.sync.is_empty\ and not cluster.sync.matches(candidate, True)\ and not click.confirm(f'Are you sure you want to failover to the asynchronous node {candidate}'): raise PatroniCtlException('Aborting ' + action) @@ -1276,8 +1275,7 @@ def _do_failover_or_switchover(obj: Dict[str, Any], action: str, cluster_name: s scheduled_at = parse_scheduled(scheduled) if scheduled_at: - from patroni.config import get_global_config - if get_global_config(cluster).is_paused: + if global_config.is_paused: raise PatroniCtlException("Can't schedule switchover in the paused state") scheduled_at_str = scheduled_at.isoformat() @@ -1293,7 +1291,7 @@ def _do_failover_or_switchover(obj: Dict[str, Any], action: str, cluster_name: s if not force: demote_msg = f', demoting current leader {cluster.leader.name}' if cluster.leader else '' if scheduled_at_str: - assert action == 'switchover' + # only switchover can be scheduled if not click.confirm(f'Are you sure you want to schedule switchover of cluster \ {cluster_name} at {scheduled_at_str}{demote_msg}?'): raise PatroniCtlException('Aborting scheduled ' + action) @@ -1722,7 +1720,6 @@ def wait_until_pause_is_applied(dcs: AbstractDCS, paused: bool, old_cluster: Clu :param old_cluster: original cluster information before pause or unpause has been requested. Used to report which nodes are still pending to have ``pause`` equal *paused* at a given point in time. """ - from patroni.config import get_global_config config = get_global_config(old_cluster) click.echo("'{0}' request sent, waiting until it is recognized by all nodes".format(paused and 'pause' or 'resume')) @@ -1760,7 +1757,6 @@ def toggle_pause(config: Dict[str, Any], cluster_name: str, group: Optional[int] * ``pause`` state is already *paused*; or * cluster contains no accessible members. """ - from patroni.config import get_global_config dcs = get_dcs(config, cluster_name, group) cluster = dcs.get_cluster() if get_global_config(cluster).is_paused == paused: