Upgrades, add keystone authentification for ostf checker
In case if there is problem with conectivity between ostf and keystone container, ostf checker won't catch and user can get broken ostf. * created separate module clients * extracted keystone client in separate class * added ostf client which uses keystone authentification Closes-bug: #1363054 Change-Id: If5bd2fb6a5736bd043171489ef9615f376a9ed75
This commit is contained in:
parent
a762c6029b
commit
03cdcd640e
@ -22,7 +22,7 @@ import six
|
||||
from fuel_upgrade import errors
|
||||
from fuel_upgrade import utils
|
||||
|
||||
from fuel_upgrade.nailgun_client import NailgunClient
|
||||
from fuel_upgrade.clients import NailgunClient
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2014 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from fuel_upgrade.clients.keystone_client import KeystoneClient
|
||||
from fuel_upgrade.clients.nailgun_client import NailgunClient
|
||||
from fuel_upgrade.clients.ostf_client import OSTFClient
|
||||
from fuel_upgrade.clients.supervisor_client import SupervisorClient
|
@ -0,0 +1,81 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2014 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import logging
|
||||
import requests
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class KeystoneClient(object):
|
||||
"""Simple keystone authentification client
|
||||
|
||||
:param str username: is user name
|
||||
:param str password: is user password
|
||||
:param str auth_url: authentification url
|
||||
:param str tenant_name: tenant name
|
||||
"""
|
||||
|
||||
def __init__(self, username=None, password=None,
|
||||
auth_url=None, tenant_name=None):
|
||||
self.auth_url = auth_url
|
||||
self.tenant_name = tenant_name
|
||||
self.username = username
|
||||
self.password = password
|
||||
|
||||
@property
|
||||
def request(self):
|
||||
"""Creates authentification session if required
|
||||
|
||||
:returns: :class:`requests.Session` object
|
||||
"""
|
||||
session = requests.Session()
|
||||
token = self.get_token()
|
||||
if token:
|
||||
session.headers.update({'X-Auth-Token': token})
|
||||
|
||||
return session
|
||||
|
||||
def get_token(self):
|
||||
"""Retrieves auth token from keystone
|
||||
|
||||
:returns: authentification token or None in case of error
|
||||
|
||||
NOTE(eli): for 5.0.x versions of fuel we don't
|
||||
have keystone and fuel access control feature,
|
||||
as result this client should work with and without
|
||||
authentication, in order to do this, we are
|
||||
trying to create Keystone client and in case if
|
||||
it fails we don't use authentication
|
||||
"""
|
||||
try:
|
||||
resp = requests.post(
|
||||
self.auth_url,
|
||||
headers={'content-type': 'application/json'},
|
||||
data=json.dumps({
|
||||
'auth': {
|
||||
'tenantName': self.tenant_name,
|
||||
'passwordCredentials': {
|
||||
'username': self.username,
|
||||
'password': self.password}}})).json()
|
||||
|
||||
return (isinstance(resp, dict) and
|
||||
resp.get('access', {}).get('token', {}).get('id'))
|
||||
except (ValueError, requests.exceptions.RequestException) as exc:
|
||||
logger.debug('Cannot authenticate in keystone: {0}'.format(exc))
|
||||
|
||||
return None
|
@ -16,7 +16,8 @@
|
||||
|
||||
import json
|
||||
import logging
|
||||
import requests
|
||||
|
||||
from fuel_upgrade.clients import KeystoneClient
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -35,11 +36,11 @@ class NailgunClient(object):
|
||||
|
||||
api_url = 'http://{host}:{port}/api/v1'
|
||||
|
||||
def __init__(self, host=None, port=None, keystone_credentials=None):
|
||||
def __init__(self, host=None, port=None, keystone_credentials={}):
|
||||
#: an url to nailgun's restapi service
|
||||
self.api_url = self.api_url.format(host=host, port=port)
|
||||
#: keystone credentials for nailgun authentification
|
||||
self.keystone_credentials = keystone_credentials
|
||||
#: keystone credentials for authentification
|
||||
self.keystone_client = KeystoneClient(**keystone_credentials)
|
||||
|
||||
def get_releases(self):
|
||||
"""Returns a list with all releases.
|
||||
@ -130,43 +131,4 @@ class NailgunClient(object):
|
||||
|
||||
:returns: :class:`requests.Session` object
|
||||
"""
|
||||
session = requests.Session()
|
||||
token = self.get_token()
|
||||
if token:
|
||||
session.headers.update({'X-Auth-Token': token})
|
||||
|
||||
return session
|
||||
|
||||
def get_token(self):
|
||||
"""Retrieves auth token from keystone
|
||||
|
||||
:returns: authentification token
|
||||
|
||||
NOTE(eli): for 5.0.x versions of fuel we don't
|
||||
have keystone and fuel access control feature,
|
||||
as result this client should work with and without
|
||||
authentication, in order to do this, we are
|
||||
trying to create Keystone client and in case if
|
||||
it fails we don't use authentication
|
||||
"""
|
||||
if not self.keystone_credentials:
|
||||
return None
|
||||
|
||||
try:
|
||||
auth_data = self.keystone_credentials
|
||||
resp = requests.post(
|
||||
auth_data['auth_url'],
|
||||
headers={'content-type': 'application/json'},
|
||||
data=json.dumps({
|
||||
'auth': {
|
||||
'tenantName': auth_data['tenant_name'],
|
||||
'passwordCredentials': {
|
||||
'username': auth_data['username'],
|
||||
'password': auth_data['password']}}})).json()
|
||||
|
||||
return (isinstance(resp, dict) and
|
||||
resp.get('access', {}).get('token', {}).get('id'))
|
||||
except (ValueError, requests.exceptions.RequestException) as exc:
|
||||
logger.debug('Cannot authenticate in keystone: {0}'.format(exc))
|
||||
|
||||
return None
|
||||
return self.keystone_client.request
|
@ -0,0 +1,60 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2014 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
|
||||
from fuel_upgrade.clients import KeystoneClient
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OSTFClient(object):
|
||||
"""OSTFClient is a simple wrapper around OSTF API.
|
||||
|
||||
:param str host: ostf's host address
|
||||
:param (str|int) port: ostf's port number
|
||||
:param dict keystone_credentials: keystone credentials where
|
||||
`username` is user name
|
||||
`password` is user password
|
||||
`auth_url` authentification url
|
||||
`tenant_name` tenant name
|
||||
"""
|
||||
|
||||
api_url = 'http://{host}:{port}'
|
||||
|
||||
def __init__(self, host=None, port=None, keystone_credentials={}):
|
||||
#: an url to nailgun's restapi service
|
||||
self.api_url = self.api_url.format(host=host, port=port)
|
||||
#: keystone credentials for authentification
|
||||
self.keystone_client = KeystoneClient(**keystone_credentials)
|
||||
|
||||
@property
|
||||
def request(self):
|
||||
"""Creates authentification session if required
|
||||
|
||||
:returns: :class:`requests.Session` object
|
||||
"""
|
||||
return self.keystone_client.request
|
||||
|
||||
def get(self, path):
|
||||
"""Retrieve list of tasks from nailgun
|
||||
|
||||
:returns: list of tasks
|
||||
"""
|
||||
result = self.request.get('{api_url}{path}'.format(
|
||||
api_url=self.api_url, path=path))
|
||||
|
||||
return result
|
@ -58,7 +58,7 @@ class SupervisorClient(object):
|
||||
"""RPC Client for supervisor
|
||||
"""
|
||||
templates_dir = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), 'templates'))
|
||||
os.path.join(os.path.dirname(__file__), '..', 'templates'))
|
||||
|
||||
def __init__(self, config, from_version):
|
||||
"""Create supervisor client
|
@ -121,15 +121,17 @@ def get_endpoints(astute_config):
|
||||
rabbitmq_mcollective_access = astute_config.get(
|
||||
'mcollective', {'user': 'mcollective', 'password': 'marionette'})
|
||||
|
||||
keystone_credentials = {
|
||||
'username': fuel_access['user'],
|
||||
'password': fuel_access['password'],
|
||||
'auth_url': 'http://{0}:5000/v2.0/tokens'.format(master_ip),
|
||||
'tenant_name': 'admin'}
|
||||
|
||||
return {
|
||||
'nginx_nailgun': {
|
||||
'port': 8000,
|
||||
'host': '0.0.0.0',
|
||||
'keystone_credentials': {
|
||||
'username': fuel_access['user'],
|
||||
'password': fuel_access['password'],
|
||||
'auth_url': 'http://{0}:5000/v2.0/tokens'.format(master_ip),
|
||||
'tenant_name': 'admin'}},
|
||||
'keystone_credentials': keystone_credentials},
|
||||
|
||||
'nginx_repo': {
|
||||
'port': 8080,
|
||||
@ -137,7 +139,8 @@ def get_endpoints(astute_config):
|
||||
|
||||
'ostf': {
|
||||
'port': 8777,
|
||||
'host': '127.0.0.1'},
|
||||
'host': '127.0.0.1',
|
||||
'keystone_credentials': keystone_credentials},
|
||||
|
||||
'cobbler': {
|
||||
'port': 80,
|
||||
|
@ -24,9 +24,9 @@ from copy import deepcopy
|
||||
import docker
|
||||
import requests
|
||||
|
||||
from fuel_upgrade.clients import SupervisorClient
|
||||
from fuel_upgrade.engines.base import UpgradeEngine
|
||||
from fuel_upgrade.health_checker import FuelUpgradeVerify
|
||||
from fuel_upgrade.supervisor_client import SupervisorClient
|
||||
from fuel_upgrade.version_file import VersionFile
|
||||
|
||||
from fuel_upgrade import errors
|
||||
|
@ -22,8 +22,8 @@ import os
|
||||
import requests
|
||||
import six
|
||||
|
||||
from fuel_upgrade.clients import NailgunClient
|
||||
from fuel_upgrade.engines.base import UpgradeEngine
|
||||
from fuel_upgrade.nailgun_client import NailgunClient
|
||||
from fuel_upgrade import utils
|
||||
|
||||
|
||||
|
@ -25,7 +25,8 @@ import six
|
||||
from fuel_upgrade import errors
|
||||
from fuel_upgrade import utils
|
||||
|
||||
from fuel_upgrade.nailgun_client import NailgunClient
|
||||
from fuel_upgrade.clients import NailgunClient
|
||||
from fuel_upgrade.clients import OSTFClient
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -135,9 +136,6 @@ class OSTFChecker(BaseChecker):
|
||||
resp = self.safe_get('http://{host}:{port}/'.format(
|
||||
**self.endpoints['ostf']))
|
||||
|
||||
# NOTE(eli): 401 response when authorization is enabled
|
||||
# 200 when there is no authorization, remove 200 when
|
||||
# authorization is enabled by default
|
||||
return resp and (resp['code'] == 401 or resp['code'] == 200)
|
||||
|
||||
|
||||
@ -273,6 +271,24 @@ class IntegrationCheckerNginxNailgunChecker(BaseChecker):
|
||||
return resp and resp['code'] == 200
|
||||
|
||||
|
||||
class IntegrationOSTFKeystoneChecker(BaseChecker):
|
||||
|
||||
@property
|
||||
def checker_name(self):
|
||||
return 'integration_ostf_keystone'
|
||||
|
||||
def check(self):
|
||||
ostf_client = OSTFClient(**self.endpoints['ostf'])
|
||||
|
||||
def get_request():
|
||||
resp = ostf_client.get('/')
|
||||
return resp.status_code
|
||||
|
||||
code = self.make_safe_request(get_request)
|
||||
|
||||
return code == 200
|
||||
|
||||
|
||||
class KeystoneChecker(BaseChecker):
|
||||
|
||||
@property
|
||||
@ -360,6 +376,7 @@ class FuelUpgradeVerify(object):
|
||||
MCollectiveChecker,
|
||||
KeystoneChecker,
|
||||
NginxChecker,
|
||||
IntegrationOSTFKeystoneChecker,
|
||||
IntegrationCheckerNginxNailgunChecker,
|
||||
IntegrationCheckerPostgresqlNailgunNginx,
|
||||
IntegrationCheckerRabbitMQAstuteNailgun]
|
||||
|
@ -392,3 +392,15 @@ class TestCheckers(BaseTestCase):
|
||||
get_mock.return_value = result
|
||||
self.assert_checker_false(
|
||||
health_checker.IntegrationCheckerRabbitMQAstuteNailgun)
|
||||
|
||||
@mock.patch('fuel_upgrade.health_checker.BaseChecker.make_safe_request')
|
||||
def test_nailgun_checker_returns_true(self, make_request_mock):
|
||||
make_request_mock.return_value = 200
|
||||
self.assert_checker_true(
|
||||
health_checker.IntegrationOSTFKeystoneChecker)
|
||||
|
||||
@mock.patch('fuel_upgrade.health_checker.BaseChecker.make_safe_request')
|
||||
def test_nailgun_checker_returns_false(self, make_request_mock):
|
||||
make_request_mock.return_value = 401
|
||||
self.assert_checker_false(
|
||||
health_checker.IntegrationOSTFKeystoneChecker)
|
||||
|
@ -0,0 +1,50 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2014 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
import requests
|
||||
|
||||
from fuel_upgrade.clients import KeystoneClient
|
||||
from fuel_upgrade.tests import base
|
||||
|
||||
|
||||
class TestKeystoneClient(base.BaseTestCase):
|
||||
|
||||
token = {'access': {'token': {'id': 'auth_token'}}}
|
||||
|
||||
def setUp(self):
|
||||
self.credentials = {
|
||||
'username': 'some_user',
|
||||
'password': 'some_password',
|
||||
'auth_url': 'http://127.0.0.1:5000/v2',
|
||||
'tenant_name': 'some_tenant'}
|
||||
|
||||
self.keystone = KeystoneClient(**self.credentials)
|
||||
|
||||
@mock.patch('fuel_upgrade.clients.keystone_client.requests.post')
|
||||
@mock.patch('fuel_upgrade.clients.keystone_client.requests.Session')
|
||||
def test_makes_authenticated_requests(self, session, post_mock):
|
||||
post_mock.return_value.json.return_value = self.token
|
||||
self.keystone.request
|
||||
session.return_value.headers.update.assert_called_once_with(
|
||||
{'X-Auth-Token': 'auth_token'})
|
||||
|
||||
@mock.patch('fuel_upgrade.clients.keystone_client.requests.Session')
|
||||
@mock.patch('fuel_upgrade.clients.keystone_client.requests.post',
|
||||
side_effect=requests.exceptions.HTTPError(''))
|
||||
def test_does_not_fail_without_keystone(self, _, __):
|
||||
self.keystone.request
|
||||
self.assertEqual(self.keystone.get_token(), None)
|
@ -17,18 +17,23 @@
|
||||
import mock
|
||||
import requests
|
||||
|
||||
from fuel_upgrade import nailgun_client
|
||||
from fuel_upgrade.clients import NailgunClient
|
||||
from fuel_upgrade.tests import base
|
||||
|
||||
|
||||
class TestNailgunClient(base.BaseTestCase):
|
||||
def setUp(self):
|
||||
self.nailgun = nailgun_client.NailgunClient('http://127.0.0.1', 8000)
|
||||
|
||||
@mock.patch('fuel_upgrade.nailgun_client.requests.Session.post')
|
||||
def test_create_release(self, post):
|
||||
def setUp(self):
|
||||
mock_keystone = mock.MagicMock()
|
||||
self.mock_request = mock_keystone.request
|
||||
with mock.patch(
|
||||
'fuel_upgrade.clients.nailgun_client.KeystoneClient',
|
||||
return_value=mock_keystone):
|
||||
self.nailgun = NailgunClient('127.0.0.1', 8000)
|
||||
|
||||
def test_create_release(self):
|
||||
# test normal bahavior
|
||||
post.return_value = self.mock_requests_response(
|
||||
self.mock_request.post.return_value = self.mock_requests_response(
|
||||
201, '{ "id": "42" }')
|
||||
|
||||
response = self.nailgun.create_release({
|
||||
@ -37,33 +42,32 @@ class TestNailgunClient(base.BaseTestCase):
|
||||
self.assertEqual(response, {'id': '42'})
|
||||
|
||||
# test failed result
|
||||
post.return_value.status_code = 409
|
||||
self.mock_request.post.return_value.status_code = 409
|
||||
self.assertRaises(
|
||||
requests.exceptions.HTTPError,
|
||||
self.nailgun.create_release,
|
||||
{'name': 'Havana on Ubuntu 12.04'})
|
||||
|
||||
@mock.patch('fuel_upgrade.nailgun_client.requests.Session.delete')
|
||||
def test_delete_release(self, delete):
|
||||
def test_delete_release(self):
|
||||
# test normal bahavior
|
||||
for status in (200, 204):
|
||||
delete.return_value = self.mock_requests_response(
|
||||
status, 'No Content')
|
||||
self.mock_request.delete.return_value = \
|
||||
self.mock_requests_response(status, 'No Content')
|
||||
response = self.nailgun.remove_release(42)
|
||||
self.assertEqual(response, 'No Content')
|
||||
|
||||
# test failed result
|
||||
delete.return_value = self.mock_requests_response(409, 'Conflict')
|
||||
self.mock_request.delete.return_value = self.mock_requests_response(
|
||||
409, 'Conflict')
|
||||
|
||||
self.assertRaises(
|
||||
requests.exceptions.HTTPError,
|
||||
self.nailgun.remove_release,
|
||||
42)
|
||||
|
||||
@mock.patch('fuel_upgrade.nailgun_client.requests.Session.post')
|
||||
def test_create_notification(self, post):
|
||||
def test_create_notification(self):
|
||||
# test normal bahavior
|
||||
post.return_value = self.mock_requests_response(
|
||||
self.mock_request.post.return_value = self.mock_requests_response(
|
||||
201,
|
||||
'{ "id": "42" }')
|
||||
|
||||
@ -74,71 +78,40 @@ class TestNailgunClient(base.BaseTestCase):
|
||||
self.assertEqual(response, {'id': '42'})
|
||||
|
||||
# test failed result
|
||||
post.return_value.status_code = 409
|
||||
self.mock_request.post.return_value.status_code = 409
|
||||
self.assertRaises(
|
||||
requests.exceptions.HTTPError,
|
||||
self.nailgun.create_notification,
|
||||
{'topic': 'release',
|
||||
'message': 'New release available!'})
|
||||
|
||||
@mock.patch('fuel_upgrade.nailgun_client.requests.Session.delete')
|
||||
def test_delete_notification(self, delete):
|
||||
def test_delete_notification(self):
|
||||
# test normal bahavior
|
||||
for status in (200, 204):
|
||||
delete.return_value = self.mock_requests_response(
|
||||
status, 'No Content')
|
||||
self.mock_request.delete.return_value = \
|
||||
self.mock_requests_response(status, 'No Content')
|
||||
response = self.nailgun.remove_notification(42)
|
||||
self.assertEqual(response, 'No Content')
|
||||
|
||||
# test failed result
|
||||
delete.return_value = self.mock_requests_response(409, 'Conflict')
|
||||
self.mock_request.delete.return_value = self.mock_requests_response(
|
||||
409, 'Conflict')
|
||||
|
||||
self.assertRaises(
|
||||
requests.exceptions.HTTPError,
|
||||
self.nailgun.remove_notification,
|
||||
42)
|
||||
|
||||
@mock.patch('fuel_upgrade.nailgun_client.requests.Session.get')
|
||||
def test_get_tasks(self, get):
|
||||
def test_get_tasks(self):
|
||||
# test positive cases
|
||||
get.return_value = self.mock_requests_response(200, '[1,2,3]')
|
||||
self.mock_request.get.return_value = self.mock_requests_response(
|
||||
200, '[1,2,3]')
|
||||
response = self.nailgun.get_tasks()
|
||||
self.assertEqual(response, [1, 2, 3])
|
||||
|
||||
# test negative cases
|
||||
get.return_value = self.mock_requests_response(502, 'Bad gateway')
|
||||
self.mock_request.get.return_value = self.mock_requests_response(
|
||||
502, 'Bad gateway')
|
||||
|
||||
self.assertRaises(
|
||||
requests.exceptions.HTTPError, self.nailgun.get_tasks)
|
||||
|
||||
|
||||
class TestNailgunClientWithAuthentification(base.BaseTestCase):
|
||||
|
||||
token = {'access': {'token': {'id': 'auth_token'}}}
|
||||
|
||||
def setUp(self):
|
||||
self.credentials = {
|
||||
'username': 'some_user',
|
||||
'password': 'some_password',
|
||||
'auth_url': 'http://127.0.0.1:5000/v2',
|
||||
'tenant_name': 'some_tenant'}
|
||||
|
||||
self.nailgun = nailgun_client.NailgunClient(
|
||||
'http://127.0.0.1',
|
||||
8000,
|
||||
keystone_credentials=self.credentials)
|
||||
|
||||
@mock.patch('fuel_upgrade.nailgun_client.requests.post')
|
||||
@mock.patch('fuel_upgrade.nailgun_client.requests.Session')
|
||||
def test_makes_authenticated_requests(self, session, post_mock):
|
||||
post_mock.return_value.json.return_value = self.token
|
||||
self.nailgun.request.get('http://some.url/path')
|
||||
session.return_value.headers.update.assert_called_once_with(
|
||||
{'X-Auth-Token': 'auth_token'})
|
||||
|
||||
@mock.patch('fuel_upgrade.nailgun_client.requests.Session')
|
||||
@mock.patch('fuel_upgrade.nailgun_client.requests.post',
|
||||
side_effect=requests.exceptions.HTTPError(''))
|
||||
def test_does_not_fail_without_keystone(self, _, __):
|
||||
self.nailgun.request.get('http://some.url/path')
|
||||
self.assertEqual(self.nailgun.get_token(), None)
|
||||
|
@ -0,0 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2014 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
|
||||
from fuel_upgrade.clients import OSTFClient
|
||||
from fuel_upgrade.tests import base
|
||||
|
||||
|
||||
class TestOSTFClient(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
mock_keystone = mock.MagicMock()
|
||||
self.mock_request = mock_keystone.request
|
||||
with mock.patch(
|
||||
'fuel_upgrade.clients.ostf_client.KeystoneClient',
|
||||
return_value=mock_keystone):
|
||||
self.ostf = OSTFClient('127.0.0.1', 8777)
|
||||
|
||||
def test_get(self):
|
||||
self.ostf.get('/some_path')
|
||||
self.mock_request.get.assert_called_once_with(
|
||||
'http://127.0.0.1:8777/some_path')
|
@ -17,15 +17,16 @@
|
||||
import mock
|
||||
import xmlrpclib
|
||||
|
||||
from fuel_upgrade.supervisor_client import SupervisorClient
|
||||
from fuel_upgrade.clients import SupervisorClient
|
||||
from fuel_upgrade.tests.base import BaseTestCase
|
||||
|
||||
|
||||
@mock.patch('fuel_upgrade.supervisor_client.os')
|
||||
@mock.patch('fuel_upgrade.clients.supervisor_client.os')
|
||||
class TestSupervisorClient(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.utils_patcher = mock.patch('fuel_upgrade.supervisor_client.utils')
|
||||
self.utils_patcher = mock.patch(
|
||||
'fuel_upgrade.clients.supervisor_client.utils')
|
||||
self.utils_mock = self.utils_patcher.start()
|
||||
|
||||
self.supervisor = SupervisorClient(self.fake_config, '0')
|
||||
@ -78,7 +79,7 @@ class TestSupervisorClient(BaseTestCase):
|
||||
|
||||
def test_generate_config(self, _):
|
||||
config_path = '/config/path'
|
||||
with mock.patch('fuel_upgrade.supervisor_client.os.path.join',
|
||||
with mock.patch('fuel_upgrade.clients.supervisor_client.os.path.join',
|
||||
return_value=config_path):
|
||||
self.supervisor.generate_config(
|
||||
{'service_name': 'service_name1', 'command': 'command1'})
|
||||
@ -94,7 +95,7 @@ class TestSupervisorClient(BaseTestCase):
|
||||
paths = ['script_path', '/path/cobbler_config', '']
|
||||
self.supervisor.generate_config = mock.MagicMock()
|
||||
with mock.patch(
|
||||
'fuel_upgrade.supervisor_client.os.path.join',
|
||||
'fuel_upgrade.clients.supervisor_client.os.path.join',
|
||||
side_effect=paths):
|
||||
|
||||
self.supervisor.generate_cobbler_config(
|
||||
|
Loading…
Reference in New Issue
Block a user