Merge "Validate discovery url when create a bay"

This commit is contained in:
Jenkins 2016-06-30 01:19:49 +00:00 committed by Gerrit Code Review
commit 4d1d73b90e
5 changed files with 232 additions and 18 deletions

View File

@ -154,6 +154,19 @@ class GetDiscoveryUrlFailed(MagnumException):
message = _("Failed to get discovery url from '%(discovery_endpoint)s'.")
class InvalidBayDiscoveryURL(Invalid):
message = _("Invalid discovery URL '%(discovery_url)s'.")
class InvalidClusterSize(Invalid):
message = _("Expected cluster size %(expect_size)d but get cluster "
"size %(size)d from '%(discovery_url)s'.")
class GetClusterSizeFailed(MagnumException):
message = _("Failed to get the size of cluster from '%(discovery_url)s'.")
class InvalidIdentity(Invalid):
message = _("Expected an uuid or int but received %(identity)s.")

View File

@ -12,11 +12,13 @@
# License for the specific language governing permissions and limitations
# under the License.
import abc
import ast
from oslo_config import cfg
from oslo_log import log as logging
from pkg_resources import iter_entry_points
import requests
from requests import exceptions as req_exceptions
import six
from magnum.common import clients
@ -394,8 +396,48 @@ class BaseTemplateDefinition(TemplateDefinition):
extra_params=extra_params,
**kwargs)
def validate_discovery_url(self, discovery_url, expect_size):
url = str(discovery_url)
if url[len(url)-1] == '/':
url += '_config/size'
else:
url += '/_config/size'
try:
result = requests.get(url).text
except req_exceptions.RequestException as err:
LOG.error(six.text_type(err))
raise exception.GetClusterSizeFailed(
discovery_url=discovery_url)
try:
result = ast.literal_eval(result)
except (ValueError, SyntaxError):
raise exception.InvalidBayDiscoveryURL(
discovery_url=discovery_url)
node_value = result.get('node', None)
if node_value is None:
raise exception.InvalidBayDiscoveryURL(
discovery_url=discovery_url)
value = node_value.get('value', None)
if value is None:
raise exception.InvalidBayDiscoveryURL(
discovery_url=discovery_url)
elif int(value) != expect_size:
raise exception.InvalidClusterSize(
expect_size=expect_size,
size=int(value),
discovery_url=discovery_url)
def get_discovery_url(self, bay):
if hasattr(bay, 'discovery_url') and bay.discovery_url:
if getattr(bay, 'master_count', None) is not None:
self.validate_discovery_url(bay.discovery_url,
bay.master_count)
else:
self.validate_discovery_url(bay.discovery_url, 1)
discovery_url = bay.discovery_url
else:
discovery_endpoint = (
@ -403,7 +445,7 @@ class BaseTemplateDefinition(TemplateDefinition):
{'size': bay.master_count})
try:
discovery_url = requests.get(discovery_endpoint).text
except Exception as err:
except req_exceptions.RequestException as err:
LOG.error(six.text_type(err))
raise exception.GetDiscoveryUrlFailed(
discovery_endpoint=discovery_endpoint)

View File

@ -81,16 +81,19 @@ class TestBayConductorWithK8s(base.TestCase):
self.mock_osc.keystone.return_value = self.mock_keystone
self.mock_osc_class.return_value = self.mock_osc
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition(
self,
mock_objects_baymodel_get_by_uuid):
mock_objects_baymodel_get_by_uuid,
mock_get):
self._test_extract_template_definition(
mock_objects_baymodel_get_by_uuid)
mock_objects_baymodel_get_by_uuid, mock_get)
def _test_extract_template_definition(
self,
mock_objects_baymodel_get_by_uuid,
mock_get,
missing_attr=None):
if missing_attr in self.baymodel_dict:
self.baymodel_dict[missing_attr] = None
@ -98,6 +101,11 @@ class TestBayConductorWithK8s(base.TestCase):
self.bay_dict[missing_attr] = None
baymodel = objects.BayModel(self.context, **self.baymodel_dict)
mock_objects_baymodel_get_by_uuid.return_value = baymodel
expected_result = str('{"action":"get","node":{"key":"test","value":'
'"1","modifiedIndex":10,"createdIndex":10}}')
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
bay = objects.Bay(self.context, **self.bay_dict)
(template_path,
@ -170,13 +178,20 @@ class TestBayConductorWithK8s(base.TestCase):
self.assertEqual(expected, definition)
self.assertEqual([], env_files)
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_with_registry(
self,
mock_objects_baymodel_get_by_uuid):
mock_objects_baymodel_get_by_uuid,
mock_get):
self.baymodel_dict['registry_enabled'] = True
baymodel = objects.BayModel(self.context, **self.baymodel_dict)
mock_objects_baymodel_get_by_uuid.return_value = baymodel
expected_result = str('{"action":"get","node":{"key":"test","value":'
'"1","modifiedIndex":10,"createdIndex":10}}')
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
bay = objects.Bay(self.context, **self.bay_dict)
cfg.CONF.set_override('swift_region',
@ -229,13 +244,20 @@ class TestBayConductorWithK8s(base.TestCase):
self.assertEqual(expected, definition)
self.assertEqual([], env_files)
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_coreos_with_disovery(
self,
mock_objects_baymodel_get_by_uuid):
mock_objects_baymodel_get_by_uuid,
mock_get):
self.baymodel_dict['cluster_distro'] = 'coreos'
baymodel = objects.BayModel(self.context, **self.baymodel_dict)
mock_objects_baymodel_get_by_uuid.return_value = baymodel
expected_result = str('{"action":"get","node":{"key":"test","value":'
'"1","modifiedIndex":10,"createdIndex":10}}')
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
bay = objects.Bay(self.context, **self.bay_dict)
(template_path,
@ -328,76 +350,103 @@ class TestBayConductorWithK8s(base.TestCase):
self.assertEqual(expected, definition)
self.assertEqual([], env_files)
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_without_dns(
self,
mock_objects_baymodel_get_by_uuid):
mock_objects_baymodel_get_by_uuid,
mock_get):
self._test_extract_template_definition(
mock_objects_baymodel_get_by_uuid,
mock_get,
missing_attr='dns_nameserver')
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_without_server_image(
self,
mock_objects_baymodel_get_by_uuid):
mock_objects_baymodel_get_by_uuid,
mock_get):
self._test_extract_template_definition(
mock_objects_baymodel_get_by_uuid,
mock_get,
missing_attr='image_id')
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_without_minion_flavor(
self,
mock_objects_baymodel_get_by_uuid):
mock_objects_baymodel_get_by_uuid,
mock_get):
self._test_extract_template_definition(
mock_objects_baymodel_get_by_uuid,
mock_get,
missing_attr='flavor_id')
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_without_docker_volume_size(
self,
mock_objects_baymodel_get_by_uuid):
mock_objects_baymodel_get_by_uuid,
mock_get):
self._test_extract_template_definition(
mock_objects_baymodel_get_by_uuid,
mock_get,
missing_attr='docker_volume_size')
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_without_docker_storage_driver(
self,
mock_objects_baymodel_get_by_uuid):
mock_objects_baymodel_get_by_uuid,
mock_get):
self._test_extract_template_definition(
mock_objects_baymodel_get_by_uuid,
mock_get,
missing_attr='docker_storage_driver')
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_without_master_flavor(
self,
mock_objects_baymodel_get_by_uuid):
mock_objects_baymodel_get_by_uuid,
mock_get):
self._test_extract_template_definition(
mock_objects_baymodel_get_by_uuid,
mock_get,
missing_attr='master_flavor_id')
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_without_apiserver_port(
self,
mock_objects_baymodel_get_by_uuid):
mock_objects_baymodel_get_by_uuid,
mock_get):
self._test_extract_template_definition(
mock_objects_baymodel_get_by_uuid,
mock_get,
missing_attr='apiserver_port')
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_without_node_count(
self,
mock_objects_baymodel_get_by_uuid):
mock_objects_baymodel_get_by_uuid,
mock_get):
self._test_extract_template_definition(
mock_objects_baymodel_get_by_uuid,
mock_get,
missing_attr='node_count')
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_without_master_count(
self,
mock_objects_baymodel_get_by_uuid):
mock_objects_baymodel_get_by_uuid,
mock_get):
self._test_extract_template_definition(
mock_objects_baymodel_get_by_uuid,
mock_get,
missing_attr='master_count')
@patch('requests.get')

View File

@ -75,12 +75,19 @@ class TestBayConductorWithSwarm(base.TestCase):
self.mock_osc_class.return_value = self.mock_osc
self.context.auth_url = 'http://192.168.10.10:5000/v3'
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_all_values(
self,
mock_objects_baymodel_get_by_uuid):
mock_objects_baymodel_get_by_uuid,
mock_get):
baymodel = objects.BayModel(self.context, **self.baymodel_dict)
mock_objects_baymodel_get_by_uuid.return_value = baymodel
expected_result = str('{"action":"get","node":{"key":"test","value":'
'"1","modifiedIndex":10,"createdIndex":10}}')
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
bay = objects.Bay(self.context, **self.bay_dict)
(template_path,
@ -121,13 +128,20 @@ class TestBayConductorWithSwarm(base.TestCase):
self.assertEqual(expected, definition)
self.assertEqual([], env_files)
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_with_registry(
self,
mock_objects_baymodel_get_by_uuid):
mock_objects_baymodel_get_by_uuid,
mock_get):
self.baymodel_dict['registry_enabled'] = True
baymodel = objects.BayModel(self.context, **self.baymodel_dict)
mock_objects_baymodel_get_by_uuid.return_value = baymodel
expected_result = str('{"action":"get","node":{"key":"test","value":'
'"1","modifiedIndex":10,"createdIndex":10}}')
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
bay = objects.Bay(self.context, **self.bay_dict)
cfg.CONF.set_override('swift_region',
@ -174,10 +188,12 @@ class TestBayConductorWithSwarm(base.TestCase):
self.assertEqual(expected, definition)
self.assertEqual([], env_files)
@patch('requests.get')
@patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_only_required(
self,
mock_objects_baymodel_get_by_uuid):
mock_objects_baymodel_get_by_uuid,
mock_get):
not_required = ['image_id', 'flavor_id', 'dns_nameserver',
'docker_volume_size', 'fixed_network', 'http_proxy',
@ -189,6 +205,11 @@ class TestBayConductorWithSwarm(base.TestCase):
baymodel = objects.BayModel(self.context, **self.baymodel_dict)
mock_objects_baymodel_get_by_uuid.return_value = baymodel
expected_result = str('{"action":"get","node":{"key":"test","value":'
'"1","modifiedIndex":10,"createdIndex":10}}')
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
bay = objects.Bay(self.context, **self.bay_dict)
(template_path,

View File

@ -14,6 +14,7 @@
import mock
from oslo_config import cfg
from requests import exceptions as req_exceptions
from magnum.common import exception
from magnum.conductor import template_definition as tdef
@ -270,6 +271,50 @@ class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
mock_get_params.assert_called_once_with(mock_context, mock_baymodel,
mock_bay, **expected_kwargs)
@mock.patch('requests.get')
def test_k8s_validate_discovery_url(self, mock_get):
expected_result = str('{"action":"get","node":{"key":"test","value":'
'"1","modifiedIndex":10,"createdIndex":10}}')
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
k8s_def = tdef.AtomicK8sTemplateDefinition()
k8s_def.validate_discovery_url('http://etcd/test', 1)
@mock.patch('requests.get')
def test_k8s_validate_discovery_url_fail(self, mock_get):
mock_get.side_effect = req_exceptions.RequestException()
k8s_def = tdef.AtomicK8sTemplateDefinition()
self.assertRaises(exception.GetClusterSizeFailed,
k8s_def.validate_discovery_url,
'http://etcd/test', 1)
@mock.patch('requests.get')
def test_k8s_validate_discovery_url_invalid(self, mock_get):
mock_resp = mock.MagicMock()
mock_resp.text = str('{"action":"get"}')
mock_get.return_value = mock_resp
k8s_def = tdef.AtomicK8sTemplateDefinition()
self.assertRaises(exception.InvalidBayDiscoveryURL,
k8s_def.validate_discovery_url,
'http://etcd/test', 1)
@mock.patch('requests.get')
def test_k8s_validate_discovery_url_unexpect_size(self, mock_get):
expected_result = str('{"action":"get","node":{"key":"test","value":'
'"1","modifiedIndex":10,"createdIndex":10}}')
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
k8s_def = tdef.AtomicK8sTemplateDefinition()
self.assertRaises(exception.InvalidClusterSize,
k8s_def.validate_discovery_url,
'http://etcd/test', 5)
@mock.patch('requests.get')
def test_k8s_get_discovery_url(self, mock_get):
cfg.CONF.set_override('etcd_discovery_service_endpoint_format',
@ -295,7 +340,7 @@ class AtomicK8sTemplateDefinitionTestCase(base.TestCase):
cfg.CONF.set_override('etcd_discovery_service_endpoint_format',
'http://etcd/test?size=%(size)d',
group='bay')
mock_get.side_effect = Exception()
mock_get.side_effect = req_exceptions.RequestException()
mock_bay = mock.MagicMock()
mock_bay.master_count = 10
mock_bay.discovery_url = None
@ -481,6 +526,50 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
mock_get_params.assert_called_once_with(mock_context, mock_baymodel,
mock_bay, **expected_kwargs)
@mock.patch('requests.get')
def test_swarm_validate_discovery_url(self, mock_get):
expected_result = str('{"action":"get","node":{"key":"test","value":'
'"1","modifiedIndex":10,"createdIndex":10}}')
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
k8s_def = tdef.AtomicK8sTemplateDefinition()
k8s_def.validate_discovery_url('http://etcd/test', 1)
@mock.patch('requests.get')
def test_swarm_validate_discovery_url_fail(self, mock_get):
mock_get.side_effect = req_exceptions.RequestException()
k8s_def = tdef.AtomicK8sTemplateDefinition()
self.assertRaises(exception.GetClusterSizeFailed,
k8s_def.validate_discovery_url,
'http://etcd/test', 1)
@mock.patch('requests.get')
def test_swarm_validate_discovery_url_invalid(self, mock_get):
mock_resp = mock.MagicMock()
mock_resp.text = str('{"action":"get"}')
mock_get.return_value = mock_resp
k8s_def = tdef.AtomicK8sTemplateDefinition()
self.assertRaises(exception.InvalidBayDiscoveryURL,
k8s_def.validate_discovery_url,
'http://etcd/test', 1)
@mock.patch('requests.get')
def test_swarm_validate_discovery_url_unexpect_size(self, mock_get):
expected_result = str('{"action":"get","node":{"key":"test","value":'
'"1","modifiedIndex":10,"createdIndex":10}}')
mock_resp = mock.MagicMock()
mock_resp.text = expected_result
mock_get.return_value = mock_resp
k8s_def = tdef.AtomicK8sTemplateDefinition()
self.assertRaises(exception.InvalidClusterSize,
k8s_def.validate_discovery_url,
'http://etcd/test', 5)
@mock.patch('requests.get')
def test_swarm_get_discovery_url(self, mock_get):
cfg.CONF.set_override('etcd_discovery_service_endpoint_format',