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)