Сегодня в очередной раз столкнулся с "сюрпризами", оставленными мне какими-то разработчиками, на этот раз объектом моих экспериментов стал OpenStack Keystone Python client (link).
Взяв пару примеров из коротких руководств я попробовал получить список OpenStack Endpoints (ссылки для доступа к OpenStack сервисам) - но не тут-то было, примеры из документации отказываются работать.
Поэкспериментировав и прочитав пару десятков страниц из гугла я не нашёл ничего "готового", однако решение было на виду.
Разбор данного примера наглядно показывает как не надо проектировать python клиентов для сервисов, чтобы ваши пользователи не сходили с ума, пытаясь их использовать.
Давайте разберём на примере.
Вот пример кода инициализации клиента из документации (ссылка):
Казалось бы - копируй и используй, так и делаем:
и при выполнении получаем ошибку:
Какой-то Endpoint не найден... так мы же как раз у него и спрашиваем список Endpoints! Что теперь делать?
Ладно, пробуем по-другому (спросим список сервисов, а не endpoints):
И снова получаем тот же трейс... хм, что-то здесь не ладное.
Может, надо указать endpoint при инициализации клиента? Пробуем (добавлен параметр во второй строке):
Получаем другой трейс, при выполнении той же строчки кода:
Про то, как ваши пользователи пытаются угадать что же нужно написать в коде, чтобы он хоть как-то начал работать, вы, возможно, узнаете только из того факта, что никто не будет пользоваться таким кодом.
Для данного кода решение оказалось следующим: для того, чтобы при инициализации клиента из примера были доступны методы работы с Services & Endpoints, необходимо так же добавить параметр project_name при создании экземпляра класса Keystone Client:
Так вот работает. Но что проблема именно в этом - совсем не очевидно, и в документации об этом тоже ничего нет.
Взяв пару примеров из коротких руководств я попробовал получить список OpenStack Endpoints (ссылки для доступа к OpenStack сервисам) - но не тут-то было, примеры из документации отказываются работать.
Поэкспериментировав и прочитав пару десятков страниц из гугла я не нашёл ничего "готового", однако решение было на виду.
Разбор данного примера наглядно показывает как не надо проектировать python клиентов для сервисов, чтобы ваши пользователи не сходили с ума, пытаясь их использовать.
Давайте разберём на примере.
Вот пример кода инициализации клиента из документации (ссылка):
from keystoneclient.v2_0 import client
username='adminUser'
password='secretword'
tenant_name='openstackDemo'
auth_url='http://192.168.206.130:5000/v2.0'
keystone = client.Client(username=username, password=password,
tenant_name=tenant_name, auth_url=auth_url)
import os
from keystoneclient.v2_0 import client as keystone_client
OS_AUTH_URL = os.environ.get('OS_AUTH_URL')
OS_USERNAME = os.environ.get('OS_USERNAME')
OS_PASSWORD = os.environ.get('OS_PASSWORD')
OS_TENANT_NAME = os.environ.get('OS_PASSWORD')
OS_PROJECT_NAME = os.environ.get('OS_PROJECT_NAME')
keystone = keystone_client.Client(auth_url=OS_AUTH_URL,
username=OS_USERNAME,
password=OS_PASSWORD,
tenat_name=OS_TENANT_NAME)
print keystone.endpoints.list()
Traceback (most recent call last):
File "test.py", line 19, in <module>
print keystone.endpoints.list()
File "/usr/lib/python2.7/dist-packages/keystoneclient/v2_0/endpoints.py", line 32, in list
return self._list('/endpoints', 'endpoints')
File "/usr/lib/python2.7/dist-packages/keystoneclient/base.py", line 124, in _list
resp, body = self.client.get(url, **kwargs)
File "/usr/lib/python2.7/dist-packages/keystoneclient/adapter.py", line 170, in get
return self.request(url, 'GET', **kwargs)
File "/usr/lib/python2.7/dist-packages/keystoneclient/adapter.py", line 206, in request
resp = super(LegacyJsonAdapter, self).request(*args, **kwargs)
File "/usr/lib/python2.7/dist-packages/keystoneclient/adapter.py", line 95, in request
return self.session.request(url, method, **kwargs)
File "/usr/lib/python2.7/dist-packages/keystoneclient/utils.py", line 337, in inner
return func(*args, **kwargs)
File "/usr/lib/python2.7/dist-packages/keystoneclient/session.py", line 328, in request
raise exceptions.EndpointNotFound()
keystoneclient.exceptions.EndpointNotFound
Ладно, пробуем по-другому (спросим список сервисов, а не endpoints):
keystone = keystone_client.Client(auth_url=OS_AUTH_URL,
username=OS_USERNAME,
password=OS_PASSWORD,
tenat_name=OS_TENANT_NAME)
print keystone.services.list()
Может, надо указать endpoint при инициализации клиента? Пробуем (добавлен параметр во второй строке):
keystone = keystone_client.Client(auth_url=OS_AUTH_URL,
endpoint=OS_ENDPOINT,
username=OS_USERNAME,
password=OS_PASSWORD,
tenat_name=OS_TENANT_NAME)
print keystone.services.list()
Traceback (most recent call last):
File "test.py", line 22, in <module>
print keystone.services.list()
File "/usr/lib/python2.7/dist-packages/keystoneclient/v2_0/services.py", line 32, in list
return self._list("/OS-KSADM/services", "OS-KSADM:services")
File "/usr/lib/python2.7/dist-packages/keystoneclient/base.py", line 124, in _list
resp, body = self.client.get(url, **kwargs)
File "/usr/lib/python2.7/dist-packages/keystoneclient/adapter.py", line 170, in get
return self.request(url, 'GET', **kwargs)
File "/usr/lib/python2.7/dist-packages/keystoneclient/adapter.py", line 206, in request
resp = super(LegacyJsonAdapter, self).request(*args, **kwargs)
File "/usr/lib/python2.7/dist-packages/keystoneclient/adapter.py", line 95, in request
return self.session.request(url, method, **kwargs)
File "/usr/lib/python2.7/dist-packages/keystoneclient/utils.py", line 337, in inner
return func(*args, **kwargs)
File "/usr/lib/python2.7/dist-packages/keystoneclient/session.py", line 308, in request
raise exceptions.AuthorizationFailure(msg)
keystoneclient.exceptions.AuthorizationFailure: No valid authentication is available
Для данного кода решение оказалось следующим: для того, чтобы при инициализации клиента из примера были доступны методы работы с Services & Endpoints, необходимо так же добавить параметр project_name при создании экземпляра класса Keystone Client:
import os
from keystoneclient.v2_0 import client as keystone_client
OS_AUTH_URL = os.environ.get('OS_AUTH_URL')
OS_USERNAME = os.environ.get('OS_USERNAME')
OS_PASSWORD = os.environ.get('OS_PASSWORD')
OS_TENANT_NAME = os.environ.get('OS_PASSWORD')
OS_PROJECT_NAME = os.environ.get('OS_PROJECT_NAME')
keystone = keystone_client.Client(auth_url=OS_AUTH_URL,
username=OS_USERNAME,
password=OS_PASSWORD,
tenat_name=OS_TENANT_NAME,
project_name=OS_PROJECT_NAME)
print keystone.endpoints.list()
print keystone.services.list()
Комментариев нет:
Отправить комментарий
Я признателен Вам за то, что делитесь своим мнением