From 8b5cb8553632c6fd9cac94b3220a3d1ccde1dcc4 Mon Sep 17 00:00:00 2001 From: Alexander Kukushkin Date: Fri, 15 Jan 2021 14:31:33 +0100 Subject: [PATCH] Exit only if authentication explicitly failed (#1806) It could happen that one of etcd servers is not accessible on Patroni start. In this case Patroni was trying to perform authentication and exiting, while it should exit only if Etcd explicitly responded with the `AuthFailed` error. Close https://github.com/zalando/patroni/issues/1805 --- patroni/dcs/etcd3.py | 6 +++++- tests/test_etcd3.py | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/patroni/dcs/etcd3.py b/patroni/dcs/etcd3.py index 1e84d5ce..2d9c0656 100644 --- a/patroni/dcs/etcd3.py +++ b/patroni/dcs/etcd3.py @@ -98,6 +98,10 @@ class UserEmpty(InvalidArgument): error = "etcdserver: user name is empty" +class AuthFailed(InvalidArgument): + error = "etcdserver: authentication failed, invalid user ID or password" + + class PermissionDenied(Etcd3ClientError): code = GRPCCode.PermissionDenied error = "etcdserver: permission denied" @@ -186,7 +190,7 @@ class Etcd3Client(AbstractEtcdClientWithFailover): try: self.authenticate() - except Exception as e: + except AuthFailed as e: logger.fatal('Etcd3 authentication failed: %r', e) sys.exit(1) diff --git a/tests/test_etcd3.py b/tests/test_etcd3.py index 6afef8f1..70f19e1d 100644 --- a/tests/test_etcd3.py +++ b/tests/test_etcd3.py @@ -5,7 +5,7 @@ import urllib3 from mock import Mock, patch from patroni.dcs.etcd3 import PatroniEtcd3Client, Cluster, Etcd3, Etcd3Error, Etcd3ClientError, RetryFailedError,\ - InvalidAuthToken, Unavailable, Unknown, UnsupportedEtcdVersion, UserEmpty, base64_encode + InvalidAuthToken, Unavailable, Unknown, UnsupportedEtcdVersion, UserEmpty, AuthFailed, base64_encode from threading import Thread from . import SleepException, MockResponse @@ -90,7 +90,7 @@ class TestKVCache(BaseTestEtcd3): class TestPatroniEtcd3Client(BaseTestEtcd3): - @patch('patroni.dcs.etcd3.Etcd3Client.authenticate', Mock(side_effect=Exception)) + @patch('patroni.dcs.etcd3.Etcd3Client.authenticate', Mock(side_effect=AuthFailed)) def test__init__(self): self.assertRaises(SystemExit, self.setUp)