commit 7f3dd65e5dc79cc456ef58a052501ec256d5070b Author: Giuseppe Lavagetto <lavagetto@gmail.com> Date: Mon Feb 13 14:12:39 2017 +0100 Support auth API both <= 2.2.5 and >= 2.3.0 Closes #210 diff --git a/src/etcd/auth.py b/src/etcd/auth.py index 796772d..c5c7346 100644 --- a/src/etcd/auth.py +++ b/src/etcd/auth.py @@ -14,13 +14,28 @@ class EtcdAuthBase(object): self.name = name self.uri = "{}/auth/{}s/{}".format(self.client.version_prefix, self.entity, self.name) + # This will be lazily evaluated if not manually set + self._legacy_api = None + + @property + def legacy_api(self): + if self._legacy_api is None: + # The auth API has changed between 2.2 and 2.3, true story! + major, minor, _ = map(int, self.client.version.split('.')) + self._legacy_api = (major < 3 and minor < 3) + return self._legacy_api + @property def names(self): key = "{}s".format(self.entity) uri = "{}/auth/{}".format(self.client.version_prefix, key) response = self.client.api_execute(uri, self.client._MGET) - return json.loads(response.data.decode('utf-8'))[key] + if self.legacy_api: + return json.loads(response.data.decode('utf-8'))[key] + else: + return [obj[self.entity] + for obj in json.loads(response.data.decode('utf-8'))[key]] def read(self): try: @@ -102,7 +117,16 @@ class EtcdUser(EtcdAuthBase): def _from_net(self, data): d = json.loads(data.decode('utf-8')) - self.roles = d.get('roles', []) + roles = d.get('roles', []) + try: + self.roles = roles + except TypeError: + # with the change of API, PUT responses are different + # from GET reponses, which makes everything so funny. + # Specifically, PUT responses are the same as before... + if self.legacy_api: + raise + self.roles = [obj['role'] for obj in roles] self.name = d.get('user') def _to_net(self, prevobj=None): diff --git a/src/etcd/tests/test_auth.py b/src/etcd/tests/test_auth.py index 14475f9..5c8c0b0 100644 --- a/src/etcd/tests/test_auth.py +++ b/src/etcd/tests/test_auth.py @@ -93,6 +93,10 @@ class EtcdUserTest(TestEtcdAuthBase): self.assertEquals(u.roles, set(['guest', 'root'])) # set roles as a list, it works! u.roles = ['guest', 'test_group'] + # We need this or the new API will return an internal error + r = auth.EtcdRole(self.client, 'test_group') + r.acls = {'*': 'R', '/test/*': 'RW'} + r.write() try: u.write() except: