711 lines
30 KiB
Python
711 lines
30 KiB
Python
# 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 socket
|
|
from unittest import mock
|
|
|
|
from keystoneauth1 import loading as ks_loading
|
|
from oslo_config import cfg
|
|
from oslo_utils import uuidutils
|
|
|
|
from senlin.common import consts
|
|
from senlin.common import exception
|
|
from senlin.common.i18n import _
|
|
from senlin.drivers import base as driver_base
|
|
from senlin.engine.actions import base as action_mod
|
|
from senlin.engine import dispatcher
|
|
from senlin.engine.receivers import message as mmod
|
|
from senlin.objects import cluster as co
|
|
from senlin.tests.unit.common import base
|
|
from senlin.tests.unit.common import utils
|
|
|
|
UUID = 'aa5f86b8-e52b-4f2b-828a-4c14c770938d'
|
|
|
|
|
|
class TestMessage(base.SenlinTestCase):
|
|
def setUp(self):
|
|
super(TestMessage, self).setUp()
|
|
self.context = utils.dummy_context()
|
|
|
|
@mock.patch.object(driver_base, 'SenlinDriver')
|
|
def test_keystone_client(self, mock_senlindriver):
|
|
sd = mock.Mock()
|
|
kc = mock.Mock()
|
|
sd.identity.return_value = kc
|
|
mock_senlindriver.return_value = sd
|
|
|
|
message = mmod.Message('message', None, None, user='user1',
|
|
project='project1')
|
|
|
|
# cached will be returned
|
|
message._keystoneclient = kc
|
|
self.assertEqual(kc, message.keystone())
|
|
|
|
# new keystone client created if no cache found
|
|
message._keystoneclient = None
|
|
params = mock.Mock()
|
|
mock_param = self.patchobject(mmod.Message, '_build_conn_params',
|
|
return_value=params)
|
|
res = message.keystone()
|
|
self.assertEqual(kc, res)
|
|
self.assertEqual(kc, message._keystoneclient)
|
|
mock_param.assert_called_once_with('user1', 'project1')
|
|
sd.identity.assert_called_once_with(params)
|
|
|
|
@mock.patch.object(driver_base, 'SenlinDriver')
|
|
def test_zaqar_client(self, mock_senlindriver):
|
|
sd = mock.Mock()
|
|
zc = mock.Mock()
|
|
sd.message.return_value = zc
|
|
mock_senlindriver.return_value = sd
|
|
|
|
message = mmod.Message('message', None, None, user='user1',
|
|
project='project1')
|
|
|
|
# cached will be returned
|
|
message._zaqarclient = zc
|
|
self.assertEqual(zc, message.zaqar())
|
|
|
|
# new zaqar client created if no cache found
|
|
message._zaqarclient = None
|
|
params = mock.Mock()
|
|
mock_param = self.patchobject(mmod.Message, '_build_conn_params',
|
|
return_value=params)
|
|
res = message.zaqar()
|
|
self.assertEqual(zc, res)
|
|
self.assertEqual(zc, message._zaqarclient)
|
|
mock_param.assert_called_once_with('user1', 'project1')
|
|
sd.message.assert_called_once_with(params)
|
|
|
|
def test_generate_subscriber_url_host_provided(self):
|
|
cfg.CONF.set_override('host', 'web.com', 'receiver')
|
|
cfg.CONF.set_override('port', '1234', 'receiver')
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
res = message._generate_subscriber_url()
|
|
|
|
expected = 'trust+http://web.com:1234/v1/receivers/%s/notify' % UUID
|
|
self.assertEqual(expected, res)
|
|
|
|
@mock.patch.object(mmod.Message, '_get_base_url')
|
|
def test_generate_subscriber_url_host_not_provided(
|
|
self, mock_get_base_url):
|
|
mock_get_base_url.return_value = 'http://web.com:1234/v1'
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
res = message._generate_subscriber_url()
|
|
|
|
expected = 'trust+http://web.com:1234/v1/receivers/%s/notify' % UUID
|
|
self.assertEqual(expected, res)
|
|
|
|
@mock.patch.object(socket, 'gethostname')
|
|
@mock.patch.object(mmod.Message, '_get_base_url')
|
|
def test_generate_subscriber_url_no_host_no_base(
|
|
self, mock_get_base_url, mock_gethostname):
|
|
mock_get_base_url.return_value = None
|
|
mock_gethostname.return_value = 'test-host'
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
res = message._generate_subscriber_url()
|
|
|
|
expected = 'trust+http://test-host:8777/v1/receivers/%s/notify' % UUID
|
|
self.assertEqual(expected, res)
|
|
|
|
def test_to_dict(self):
|
|
message = mmod.Message('message', None, None, user='user1',
|
|
project='project1', id=UUID)
|
|
message.channel = {'queue_name': 'test-queue',
|
|
'subscription': 'subscription-id'}
|
|
res = message.to_dict()
|
|
expected_res = {
|
|
'name': None,
|
|
'id': UUID,
|
|
'user': 'user1',
|
|
'project': 'project1',
|
|
'domain': '',
|
|
'type': 'message',
|
|
'channel': {'queue_name': 'test-queue'},
|
|
'action': None,
|
|
'cluster_id': None,
|
|
'actor': {},
|
|
'params': {},
|
|
'created_at': None,
|
|
'updated_at': None,
|
|
}
|
|
self.assertEqual(expected_res, res)
|
|
|
|
@mock.patch.object(mmod.Message, '_create_queue')
|
|
@mock.patch.object(mmod.Message, '_create_subscription')
|
|
def test_initialize_channel(self, mock_create_subscription,
|
|
mock_create_queue):
|
|
mock_sub = mock.Mock()
|
|
mock_sub.subscription_id = 'test-subscription-id'
|
|
mock_create_subscription.return_value = mock_sub
|
|
mock_create_queue.return_value = 'test-queue'
|
|
|
|
message = mmod.Message('message', None, None)
|
|
res = message.initialize_channel(self.context)
|
|
|
|
expected_channel = {'queue_name': 'test-queue',
|
|
'subscription': 'test-subscription-id'}
|
|
self.assertEqual(expected_channel, res)
|
|
mock_create_queue.assert_called_once_with()
|
|
mock_create_subscription.assert_called_once_with('test-queue')
|
|
|
|
@mock.patch.object(mmod.Message, 'zaqar')
|
|
def test_create_queue(self, mock_zaqar):
|
|
cfg.CONF.set_override('max_message_size', 8192, 'receiver')
|
|
mock_zc = mock.Mock()
|
|
mock_zaqar.return_value = mock_zc
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
queue_name = 'senlin-receiver-%s' % message.id
|
|
kwargs = {
|
|
'_max_messages_post_size': 8192,
|
|
'description': 'Senlin receiver %s.' % message.id,
|
|
'name': queue_name
|
|
}
|
|
mock_zc.queue_create.return_value = queue_name
|
|
res = message._create_queue()
|
|
|
|
self.assertEqual(queue_name, res)
|
|
mock_zc.queue_create.assert_called_once_with(**kwargs)
|
|
|
|
@mock.patch.object(mmod.Message, 'zaqar')
|
|
def test_create_queue_fail(self, mock_zaqar):
|
|
cfg.CONF.set_override('max_message_size', 8192, 'receiver')
|
|
mock_zc = mock.Mock()
|
|
mock_zaqar.return_value = mock_zc
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
queue_name = 'senlin-receiver-%s' % message.id
|
|
kwargs = {
|
|
'_max_messages_post_size': 8192,
|
|
'description': 'Senlin receiver %s.' % message.id,
|
|
'name': queue_name
|
|
}
|
|
mock_zc.queue_create.side_effect = exception.InternalError()
|
|
self.assertRaises(exception.EResourceCreation, message._create_queue)
|
|
mock_zc.queue_create.assert_called_once_with(**kwargs)
|
|
|
|
@mock.patch.object(mmod.Message, '_generate_subscriber_url')
|
|
@mock.patch.object(mmod.Message, '_build_trust')
|
|
@mock.patch.object(mmod.Message, 'zaqar')
|
|
def test_create_subscription(self, mock_zaqar, mock_build_trust,
|
|
mock_generate_subscriber_url):
|
|
mock_zc = mock.Mock()
|
|
mock_zaqar.return_value = mock_zc
|
|
mock_build_trust.return_value = '123abc'
|
|
subscriber = 'subscriber_url'
|
|
mock_generate_subscriber_url.return_value = subscriber
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
queue_name = 'test-queue'
|
|
kwargs = {
|
|
"ttl": 2 ** 36,
|
|
"subscriber": subscriber,
|
|
"options": {
|
|
"trust_id": "123abc"
|
|
}
|
|
}
|
|
mock_zc.subscription_create.return_value = 'subscription'
|
|
res = message._create_subscription(queue_name)
|
|
|
|
self.assertEqual('subscription', res)
|
|
mock_generate_subscriber_url.assert_called_once_with()
|
|
mock_zc.subscription_create.assert_called_once_with(queue_name,
|
|
**kwargs)
|
|
|
|
@mock.patch.object(mmod.Message, '_generate_subscriber_url')
|
|
@mock.patch.object(mmod.Message, '_build_trust')
|
|
@mock.patch.object(mmod.Message, 'zaqar')
|
|
def test_create_subscription_fail(self, mock_zaqar, mock_build_trust,
|
|
mock_generate_subscriber_url):
|
|
mock_zc = mock.Mock()
|
|
mock_zaqar.return_value = mock_zc
|
|
mock_build_trust.return_value = '123abc'
|
|
subscriber = 'subscriber_url'
|
|
mock_generate_subscriber_url.return_value = subscriber
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
message.id = UUID
|
|
queue_name = 'test-queue'
|
|
kwargs = {
|
|
"ttl": 2 ** 36,
|
|
"subscriber": subscriber,
|
|
"options": {
|
|
"trust_id": "123abc"
|
|
}
|
|
}
|
|
|
|
mock_zc.subscription_create.side_effect = exception.InternalError()
|
|
self.assertRaises(exception.EResourceCreation,
|
|
message._create_subscription, queue_name)
|
|
mock_generate_subscriber_url.assert_called_once_with()
|
|
mock_zc.subscription_create.assert_called_once_with(queue_name,
|
|
**kwargs)
|
|
|
|
@mock.patch.object(mmod.Message, 'zaqar')
|
|
def test_release_channel(self, mock_zaqar):
|
|
mock_zc = mock.Mock()
|
|
mock_zaqar.return_value = mock_zc
|
|
channel = {'queue_name': 'test-queue',
|
|
'subscription': 'test-subscription-id'}
|
|
message = mmod.Message('message', None, None, id=UUID,
|
|
channel=channel)
|
|
|
|
message.release_channel(self.context)
|
|
mock_zc.subscription_delete.assert_called_once_with(
|
|
'test-queue', 'test-subscription-id')
|
|
mock_zc.queue_delete.assert_called_once_with('test-queue')
|
|
|
|
@mock.patch.object(mmod.Message, 'zaqar')
|
|
def test_release_channel_subscription_delete_fail(self, mock_zaqar):
|
|
mock_zc = mock.Mock()
|
|
mock_zaqar.return_value = mock_zc
|
|
channel = {'queue_name': 'test-queue',
|
|
'subscription': 'test-subscription-id'}
|
|
message = mmod.Message('message', None, None, id=UUID,
|
|
channel=channel)
|
|
mock_zc.subscription_delete.side_effect = exception.InternalError()
|
|
|
|
self.assertRaises(exception.EResourceDeletion,
|
|
message.release_channel, self.context)
|
|
mock_zc.subscription_delete.assert_called_once_with(
|
|
'test-queue', 'test-subscription-id')
|
|
|
|
@mock.patch.object(mmod.Message, 'zaqar')
|
|
def test_release_channel_queue_delete_fail(self, mock_zaqar):
|
|
mock_zc = mock.Mock()
|
|
mock_zaqar.return_value = mock_zc
|
|
channel = {'queue_name': 'test-queue',
|
|
'subscription': 'test-subscription-id'}
|
|
message = mmod.Message('message', None, None, id=UUID,
|
|
channel=channel)
|
|
mock_zc.queue_delete.side_effect = exception.InternalError()
|
|
|
|
self.assertRaises(exception.EResourceDeletion,
|
|
message.release_channel, self.context)
|
|
mock_zc.subscription_delete.assert_called_once_with(
|
|
'test-queue', 'test-subscription-id')
|
|
mock_zc.queue_delete.assert_called_once_with('test-queue')
|
|
|
|
@mock.patch.object(ks_loading, 'load_auth_from_conf_options')
|
|
@mock.patch.object(ks_loading, 'load_session_from_conf_options')
|
|
@mock.patch.object(mmod.Message, 'keystone')
|
|
def test_build_trust_exists(self, mock_keystone, mock_load_session,
|
|
mock_load_auth):
|
|
mock_auth = mock.Mock()
|
|
mock_session = mock.Mock()
|
|
mock_session.get_user_id.return_value = 'zaqar-trustee-user-id'
|
|
mock_load_session.return_value = mock_session
|
|
mock_load_auth.return_value = mock_auth
|
|
mock_kc = mock.Mock()
|
|
mock_keystone.return_value = mock_kc
|
|
mock_trust = mock.Mock()
|
|
mock_trust.id = 'mock-trust-id'
|
|
message = mmod.Message('message', None, None, id=UUID,
|
|
user='user1', project='project1',
|
|
params={'notifier_roles': ['test-role']})
|
|
mock_kc.trust_get_by_trustor.return_value = mock_trust
|
|
|
|
res = message._build_trust()
|
|
|
|
self.assertEqual('mock-trust-id', res)
|
|
mock_kc.trust_get_by_trustor.assert_called_once_with(
|
|
'user1', 'zaqar-trustee-user-id', 'project1')
|
|
mock_load_auth.assert_called_once_with(cfg.CONF, 'zaqar')
|
|
mock_load_session.assert_called_once_with(cfg.CONF, 'zaqar')
|
|
mock_session.get_user_id.assert_called_once_with(auth=mock_auth)
|
|
|
|
@mock.patch.object(ks_loading, 'load_auth_from_conf_options')
|
|
@mock.patch.object(ks_loading, 'load_session_from_conf_options')
|
|
@mock.patch.object(mmod.Message, 'keystone')
|
|
def test_build_trust_create_new_multiroles(
|
|
self, mock_keystone, mock_load_session, mock_load_auth):
|
|
mock_auth = mock.Mock()
|
|
mock_session = mock.Mock()
|
|
mock_session.get_user_id.return_value = 'zaqar-trustee-user-id'
|
|
mock_load_session.return_value = mock_session
|
|
mock_load_auth.return_value = mock_auth
|
|
mock_kc = mock.Mock()
|
|
mock_keystone.return_value = mock_kc
|
|
mock_trust = mock.Mock()
|
|
mock_trust.id = 'mock-trust-id'
|
|
message = mmod.Message('message', None, None, id=UUID,
|
|
user='user1', project='project1')
|
|
message.notifier_roles = ['test_role']
|
|
mock_kc.trust_get_by_trustor.return_value = None
|
|
mock_kc.trust_create.return_value = mock_trust
|
|
|
|
res = message._build_trust()
|
|
|
|
self.assertEqual('mock-trust-id', res)
|
|
mock_kc.trust_get_by_trustor.assert_called_once_with(
|
|
'user1', 'zaqar-trustee-user-id', 'project1')
|
|
mock_kc.trust_create.assert_called_once_with(
|
|
'user1', 'zaqar-trustee-user-id', 'project1', ['test_role'])
|
|
|
|
@mock.patch.object(ks_loading, 'load_auth_from_conf_options')
|
|
@mock.patch.object(ks_loading, 'load_session_from_conf_options')
|
|
@mock.patch.object(mmod.Message, 'keystone')
|
|
def test_build_trust_create_new_single_admin_role(
|
|
self, mock_keystone, mock_load_session, mock_load_auth):
|
|
mock_auth = mock.Mock()
|
|
mock_session = mock.Mock()
|
|
mock_session.get_user_id.return_value = 'zaqar-trustee-user-id'
|
|
mock_load_session.return_value = mock_session
|
|
mock_load_auth.return_value = mock_auth
|
|
mock_kc = mock.Mock()
|
|
mock_keystone.return_value = mock_kc
|
|
mock_trust = mock.Mock()
|
|
mock_trust.id = 'mock-trust-id'
|
|
message = mmod.Message('message', None, None, id=UUID,
|
|
user='user1', project='project1')
|
|
message.notifier_roles = ['admin']
|
|
mock_kc.trust_get_by_trustor.return_value = None
|
|
mock_kc.trust_create.return_value = mock_trust
|
|
|
|
res = message._build_trust()
|
|
|
|
self.assertEqual('mock-trust-id', res)
|
|
mock_kc.trust_get_by_trustor.assert_called_once_with(
|
|
'user1', 'zaqar-trustee-user-id', 'project1')
|
|
mock_kc.trust_create.assert_called_once_with(
|
|
'user1', 'zaqar-trustee-user-id', 'project1', ['admin'])
|
|
|
|
@mock.patch.object(ks_loading, 'load_auth_from_conf_options')
|
|
@mock.patch.object(ks_loading, 'load_session_from_conf_options')
|
|
@mock.patch.object(mmod.Message, 'keystone')
|
|
def test_build_trust_create_new_trust_failed(self, mock_keystone,
|
|
mock_load_session,
|
|
mock_load_auth):
|
|
mock_auth = mock.Mock()
|
|
mock_session = mock.Mock()
|
|
mock_session.get_user_id.return_value = 'zaqar-trustee-user-id'
|
|
mock_load_session.return_value = mock_session
|
|
mock_load_auth.return_value = mock_auth
|
|
mock_kc = mock.Mock()
|
|
mock_keystone.return_value = mock_kc
|
|
mock_trust = mock.Mock()
|
|
mock_trust.id = 'mock-trust-id'
|
|
message = mmod.Message('message', None, None, id=UUID,
|
|
user='user1', project='project1')
|
|
message.notifier_roles = ['test_role']
|
|
mock_kc.trust_get_by_trustor.return_value = None
|
|
mock_kc.trust_create.side_effect = exception.InternalError()
|
|
|
|
self.assertRaises(exception.EResourceCreation,
|
|
message._build_trust)
|
|
|
|
mock_kc.trust_get_by_trustor.assert_called_once_with(
|
|
'user1', 'zaqar-trustee-user-id', 'project1')
|
|
mock_kc.trust_create.assert_called_once_with(
|
|
'user1', 'zaqar-trustee-user-id', 'project1', ['test_role'])
|
|
|
|
@mock.patch.object(ks_loading, 'load_auth_from_conf_options')
|
|
@mock.patch.object(ks_loading, 'load_session_from_conf_options')
|
|
@mock.patch.object(mmod.Message, 'keystone')
|
|
def test_build_trust_get_trust_exception(self, mock_keystone,
|
|
mock_load_session,
|
|
mock_load_auth):
|
|
mock_auth = mock.Mock()
|
|
mock_session = mock.Mock()
|
|
mock_session.get_user_id.return_value = 'zaqar-trustee-user-id'
|
|
mock_load_session.return_value = mock_session
|
|
mock_load_auth.return_value = mock_auth
|
|
mock_kc = mock.Mock()
|
|
mock_keystone.return_value = mock_kc
|
|
mock_trust = mock.Mock()
|
|
mock_trust.id = 'mock-trust-id'
|
|
message = mmod.Message('message', None, None, id=UUID,
|
|
user='user1', project='project1')
|
|
mock_kc.trust_get_by_trustor.side_effect = exception.InternalError()
|
|
|
|
self.assertRaises(exception.EResourceCreation,
|
|
message._build_trust)
|
|
|
|
mock_kc.trust_get_by_trustor.assert_called_once_with(
|
|
'user1', 'zaqar-trustee-user-id', 'project1')
|
|
|
|
@mock.patch.object(co.Cluster, 'get')
|
|
def test_find_cluster_by_uuid(self, mock_get):
|
|
x_cluster = mock.Mock()
|
|
mock_get.return_value = x_cluster
|
|
|
|
aid = uuidutils.generate_uuid()
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
result = message._find_cluster(self.context, aid)
|
|
|
|
self.assertEqual(x_cluster, result)
|
|
mock_get.assert_called_once_with(self.context, aid)
|
|
|
|
@mock.patch.object(co.Cluster, 'get_by_name')
|
|
@mock.patch.object(co.Cluster, 'get')
|
|
def test_find_cluster_by_uuid_as_name(self, mock_get, mock_get_name):
|
|
x_cluster = mock.Mock()
|
|
mock_get_name.return_value = x_cluster
|
|
mock_get.return_value = None
|
|
|
|
aid = uuidutils.generate_uuid()
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
result = message._find_cluster(self.context, aid)
|
|
|
|
self.assertEqual(x_cluster, result)
|
|
mock_get.assert_called_once_with(self.context, aid)
|
|
mock_get_name.assert_called_once_with(self.context, aid)
|
|
|
|
@mock.patch.object(co.Cluster, 'get_by_name')
|
|
def test_find_cluster_by_name(self, mock_get_name):
|
|
x_cluster = mock.Mock()
|
|
mock_get_name.return_value = x_cluster
|
|
|
|
aid = 'this-is-not-uuid'
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
result = message._find_cluster(self.context, aid)
|
|
|
|
self.assertEqual(x_cluster, result)
|
|
mock_get_name.assert_called_once_with(self.context, aid)
|
|
|
|
@mock.patch.object(co.Cluster, 'get_by_short_id')
|
|
@mock.patch.object(co.Cluster, 'get_by_name')
|
|
def test_find_cluster_by_shortid(self, mock_get_name, mock_get_shortid):
|
|
x_cluster = mock.Mock()
|
|
mock_get_shortid.return_value = x_cluster
|
|
mock_get_name.return_value = None
|
|
|
|
aid = 'abcd-1234-abcd'
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
result = message._find_cluster(self.context, aid)
|
|
|
|
self.assertEqual(x_cluster, result)
|
|
mock_get_name.assert_called_once_with(self.context, aid)
|
|
mock_get_shortid.assert_called_once_with(self.context, aid)
|
|
|
|
@mock.patch.object(co.Cluster, 'get_by_name')
|
|
def test_find_cluster_not_found(self, mock_get_name):
|
|
mock_get_name.return_value = None
|
|
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
self.assertRaises(exception.ResourceNotFound, message._find_cluster,
|
|
self.context, 'bogus')
|
|
|
|
mock_get_name.assert_called_once_with(self.context, 'bogus')
|
|
|
|
@mock.patch.object(dispatcher, 'start_action')
|
|
@mock.patch.object(mmod.Message, '_build_action')
|
|
@mock.patch.object(mmod.Message, 'zaqar')
|
|
def test_notify(self, mock_zaqar, mock_build_action, mock_start_action):
|
|
mock_zc = mock.Mock()
|
|
mock_zaqar.return_value = mock_zc
|
|
mock_claim = mock.Mock()
|
|
mock_claim.id = 'claim_id'
|
|
message1 = {
|
|
'body': {'cluster': 'c1', 'action': 'CLUSTER_SCALE_IN'},
|
|
'id': 'ID1'
|
|
}
|
|
message2 = {
|
|
'body': {'cluster': 'c2', 'action': 'CLUSTER_SCALE_OUT'},
|
|
'id': 'ID2'
|
|
}
|
|
mock_claim.messages = [message1, message2]
|
|
mock_zc.claim_create.return_value = mock_claim
|
|
mock_build_action.side_effect = ['action_id1', 'action_id2']
|
|
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
message.channel = {'queue_name': 'queue1'}
|
|
res = message.notify(self.context)
|
|
self.assertEqual(['action_id1', 'action_id2'], res)
|
|
mock_zc.claim_create.assert_called_once_with('queue1')
|
|
mock_zc.claim_delete.assert_called_once_with('queue1', 'claim_id')
|
|
mock_calls = [
|
|
mock.call(self.context, message1),
|
|
mock.call(self.context, message2)
|
|
]
|
|
mock_build_action.assert_has_calls(mock_calls)
|
|
mock_start_action.assert_called_once_with()
|
|
mock_calls2 = [
|
|
mock.call('queue1', 'ID1', 'claim_id'),
|
|
mock.call('queue1', 'ID2', 'claim_id')
|
|
]
|
|
mock_zc.message_delete.assert_has_calls(mock_calls2)
|
|
|
|
@mock.patch.object(mmod.Message, 'zaqar')
|
|
def test_notify_no_message(self, mock_zaqar):
|
|
mock_zc = mock.Mock()
|
|
mock_zaqar.return_value = mock_zc
|
|
mock_claim = mock.Mock()
|
|
mock_claim.messages = None
|
|
mock_zc.claim_create.return_value = mock_claim
|
|
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
message.channel = {'queue_name': 'queue1'}
|
|
res = message.notify(self.context)
|
|
self.assertEqual([], res)
|
|
mock_zc.claim_create.assert_called_once_with('queue1')
|
|
|
|
@mock.patch.object(dispatcher, 'start_action')
|
|
@mock.patch.object(mmod.Message, '_build_action')
|
|
@mock.patch.object(mmod.Message, 'zaqar')
|
|
def test_notify_some_actions_building_failed(self, mock_zaqar,
|
|
mock_build_action,
|
|
mock_start_action):
|
|
mock_zc = mock.Mock()
|
|
mock_zaqar.return_value = mock_zc
|
|
mock_claim = mock.Mock()
|
|
mock_claim.id = 'claim_id'
|
|
message1 = {
|
|
'body': {'cluster': 'c1', 'action': 'CLUSTER_SCALE_IN'},
|
|
'id': 'ID1'
|
|
}
|
|
message2 = {
|
|
'body': {'cluster': 'foo', 'action': 'CLUSTER_SCALE_OUT'},
|
|
'id': 'ID2'
|
|
}
|
|
mock_claim.messages = [message1, message2]
|
|
mock_zc.claim_create.return_value = mock_claim
|
|
mock_build_action.side_effect = [exception.InternalError(),
|
|
'action_id1']
|
|
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
message.channel = {'queue_name': 'queue1'}
|
|
res = message.notify(self.context)
|
|
self.assertEqual(['action_id1'], res)
|
|
mock_zc.claim_create.assert_called_once_with('queue1')
|
|
mock_calls = [
|
|
mock.call(self.context, message1),
|
|
mock.call(self.context, message2)
|
|
]
|
|
mock_build_action.assert_has_calls(mock_calls)
|
|
mock_start_action.assert_called_once_with()
|
|
mock_calls2 = [
|
|
mock.call('queue1', 'ID1', 'claim_id'),
|
|
mock.call('queue1', 'ID2', 'claim_id')
|
|
]
|
|
mock_zc.message_delete.assert_has_calls(mock_calls2)
|
|
|
|
@mock.patch.object(mmod.Message, 'zaqar')
|
|
def test_notify_claiming_message_failed(self, mock_zaqar):
|
|
mock_zc = mock.Mock()
|
|
mock_zaqar.return_value = mock_zc
|
|
mock_zc.claim_create.side_effect = exception.InternalError()
|
|
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
message.channel = {'queue_name': 'queue1'}
|
|
res = message.notify(self.context)
|
|
self.assertIsNone(res)
|
|
mock_zc.claim_create.assert_called_once_with('queue1')
|
|
|
|
@mock.patch.object(action_mod.Action, 'create')
|
|
@mock.patch.object(mmod.Message, '_find_cluster')
|
|
def test_build_action(self, mock_find_cluster, mock_action_create):
|
|
fake_cluster = mock.Mock()
|
|
fake_cluster.user = 'user1'
|
|
fake_cluster.id = 'cid1'
|
|
mock_find_cluster.return_value = fake_cluster
|
|
mock_action_create.return_value = 'action_id1'
|
|
msg = {
|
|
'body': {'cluster': 'c1', 'action': 'CLUSTER_SCALE_IN'},
|
|
'id': 'ID123456'
|
|
}
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
message.id = 'ID654321'
|
|
message.user = 'user1'
|
|
expected_kwargs = {
|
|
'name': 'receiver_ID654321_ID123456',
|
|
'cause': consts.CAUSE_RPC,
|
|
'status': action_mod.Action.READY,
|
|
'inputs': {}
|
|
}
|
|
|
|
res = message._build_action(self.context, msg)
|
|
self.assertEqual('action_id1', res)
|
|
mock_find_cluster.assert_called_once_with(self.context, 'c1')
|
|
mock_action_create.assert_called_once_with(self.context, 'cid1',
|
|
'CLUSTER_SCALE_IN',
|
|
**expected_kwargs)
|
|
|
|
def test_build_action_message_body_empty(self):
|
|
msg = {
|
|
'body': {},
|
|
'id': 'ID123456'
|
|
}
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
ex = self.assertRaises(exception.InternalError, message._build_action,
|
|
self.context, msg)
|
|
ex_msg = _('Message body is empty.')
|
|
self.assertEqual(ex_msg, ex.message)
|
|
|
|
def test_build_action_no_cluster_in_message_body(self):
|
|
msg = {
|
|
'body': {'action': 'CLUSTER_SCALE_IN'},
|
|
'id': 'ID123456'
|
|
}
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
ex = self.assertRaises(exception.InternalError, message._build_action,
|
|
self.context, msg)
|
|
ex_msg = _('Both cluster identity and action must be specified.')
|
|
self.assertEqual(ex_msg, ex.message)
|
|
|
|
def test_build_action_no_action_in_message_body(self):
|
|
msg = {
|
|
'body': {'cluster': 'c1'},
|
|
'id': 'ID123456'
|
|
}
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
ex = self.assertRaises(exception.InternalError, message._build_action,
|
|
self.context, msg)
|
|
ex_msg = _('Both cluster identity and action must be specified.')
|
|
self.assertEqual(ex_msg, ex.message)
|
|
|
|
@mock.patch.object(mmod.Message, '_find_cluster')
|
|
def test_build_action_cluster_notfound(self, mock_find_cluster):
|
|
mock_find_cluster.side_effect = exception.ResourceNotFound(
|
|
type='cluster', id='c1')
|
|
msg = {
|
|
'body': {'cluster': 'c1', 'action': 'CLUSTER_SCALE_IN'},
|
|
'id': 'ID123456'
|
|
}
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
ex = self.assertRaises(exception.InternalError, message._build_action,
|
|
self.context, msg)
|
|
ex_msg = _('Cluster (c1) cannot be found.')
|
|
self.assertEqual(ex_msg, ex.message)
|
|
|
|
@mock.patch.object(mmod.Message, '_find_cluster')
|
|
def test_build_action_permission_denied(self, mock_find_cluster):
|
|
fake_cluster = mock.Mock()
|
|
fake_cluster.user = 'user1'
|
|
mock_find_cluster.return_value = fake_cluster
|
|
msg = {
|
|
'body': {'cluster': 'c1', 'action': 'CLUSTER_SCALE_IN'},
|
|
'id': 'ID123456'
|
|
}
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
message.user = 'user2'
|
|
ex = self.assertRaises(exception.InternalError, message._build_action,
|
|
self.context, msg)
|
|
ex_msg = _('%(user)s is not allowed to trigger actions on '
|
|
'cluster %(cid)s.') % {'user': message.user,
|
|
'cid': 'c1'}
|
|
self.assertEqual(ex_msg, ex.message)
|
|
|
|
@mock.patch.object(mmod.Message, '_find_cluster')
|
|
def test_build_action_invalid_action_name(self, mock_find_cluster):
|
|
fake_cluster = mock.Mock()
|
|
fake_cluster.user = 'user1'
|
|
mock_find_cluster.return_value = fake_cluster
|
|
msg = {
|
|
'body': {'cluster': 'c1', 'action': 'foo'},
|
|
'id': 'ID123456'
|
|
}
|
|
message = mmod.Message('message', None, None, id=UUID)
|
|
message.user = 'user1'
|
|
ex = self.assertRaises(exception.InternalError, message._build_action,
|
|
self.context, msg)
|
|
ex_msg = _("Illegal cluster action 'foo' specified.")
|
|
self.assertEqual(ex_msg, ex.message)
|