def test__run(self, setup, dequeue, on_started): """The _run() method can send a proper message to a worker""" f = FSM(state_id) f.reply_queue = temp_queue f.group = "mock tests" f.dynamic = {} f.active_step = _active_step_string f.active_sequence = new_active_sequence() f.execution = new_playbook()['execution'] consume_iter = [( mock.Mock(name="method_mocked"), mock.Mock(name="properties_mocked"), json.dumps(msg_completed), )] publish = mock.Mock() channel = mock.Mock() channel.consume.return_value = iter(consume_iter) channel.basic_publish = publish f.ch = channel with mock.patch('recore.amqp.MQ_CONF') as mq_conf: mq_conf = MQ_CONF f._run() setup.assert_called_once_with() dequeue.assert_called_once_with() f.ch.basic_ack.assert_called_once_with(consume_iter[0][0].delivery_tag) f.ch.cancel.assert_called_once_with() on_started.assert_called_once_with(f.ch, *consume_iter[0])
def test_step_notification_started_no_notifications(self, send_notification, on_started, dequeue_step, setup): """Per-step notifications don't happen if no notifications are defined""" f = FSM(state_id) msg_started = {'status': 'started'} consume_iter = [ (mock.Mock(name="method_mocked"), mock.Mock(name="properties_mocked"), json.dumps(msg_started)) ] # Pre-test scaffolding. Hard-code some mocked out # attributes/variables because we're skipping the usual # initialization steps. f.conn = mock.Mock(pika.connection.Connection) publish = mock.Mock() channel = mock.Mock() channel.consume.return_value = iter(consume_iter) channel.basic_publish = publish f.ch = channel f.active_sequence = {'hosts': ['localhost']} f.group = 'testgroup' f.dynamic = {} f.active_step = new_notify_step() # Run the method now. It should terminate when it reaches the # end of _run() with a call to a mocked out on_started() with mock.patch('recore.amqp.MQ_CONF') as mq_conf: mq_conf = MQ_CONF f._run() self.assertEqual(send_notification.call_count, 0)
def test_step_notification_started_two_transports(self, send_notification, on_started, dequeue_step, setup): """Per-step notifications happen for all defined transports Tests for the case where multiple notification transports (irc, email, etc) are defined""" f = FSM(TEST_PBID, state_id) msg_started = {'status': 'started'} consume_iter = [ (mock.Mock(name="method_mocked"), mock.Mock(name="properties_mocked"), json.dumps(msg_started)) ] # Pre-test scaffolding. Hard-code some mocked out # attributes/variables because we're skipping the usual # initialization steps. f.conn = mock.Mock(pika.connection.Connection) publish = mock.Mock() channel = mock.Mock() channel.consume.return_value = iter(consume_iter) channel.basic_publish = publish f.ch = channel f.active_sequence = {'hosts': ['localhost']} f.group = 'testgroup' f.dynamic = {} _step = { "service:Restart": { "service": "megafrobber", "notify": { "started": { "irc": ['#achannel'], "email": ['*****@*****.**'] } } } } f.active_step = _step # Run the method now. It should terminate when it reaches the # end of _run() with a call to a mocked out on_started() with mock.patch('recore.amqp.MQ_CONF') as mq_conf: mq_conf = MQ_CONF set_field = mock.MagicMock() filter = mock.MagicMock(return_value=set_field) f.filter = filter f._run() self.assertEqual(send_notification.call_count, 2)
def test_step_notification_failed(self, send_notification, move_remaining, setup, updatestate): """Per-step notifications work when a step fails Tests for the case where only one notification transport (irc, email, etc) is defined""" f = FSM(TEST_PBID, state_id) msg_failed = {'status': 'failed'} consume_iter = [ (mock.Mock(name="method_mocked"), mock.Mock(name="properties_mocked"), json.dumps(msg_failed)) ] # Pre-test scaffolding. Hard-code some mocked out # attributes/variables because we're skipping the usual # initialization steps. f.conn = mock.Mock(pika.connection.Connection) f.executed = [] f.execution = [] f.state_coll = {} f.post_deploy_action = [] publish = mock.Mock() channel = mock.Mock() channel.consume.return_value = iter(consume_iter) channel.basic_publish = publish f.ch = channel f.active_sequence = {'hosts': ['localhost']} f.group = 'testgroup' f.dynamic = {} f.active_step = new_notify_step('failed') set_field = mock.MagicMock() filter = mock.MagicMock(return_value=set_field) f.filter = filter # Run the ended method with a body having 'status' as failed f.on_ended(channel, mock.Mock(name="method_mocked"), mock.Mock(name="header_mocked"), json.dumps(msg_failed)) self.assertEqual(send_notification.call_count, 1) self.assertEqual(send_notification.call_args[0][1], 'notify.irc') self.assertEqual(send_notification.call_args[0][2], state_id) self.assertEqual(send_notification.call_args[0][3], ['#achannel']) self.assertEqual(send_notification.call_args[0][4], 'failed')
def test_post_deploy_passed(self, send_notification, move_active, run, skipped): """Post-deploy action passes""" f = FSM(TEST_PBID, state_id) msg_completed = {'status': 'started'} consume_iter = [ (mock.Mock(name="method_mocked"), mock.Mock(name="properties_mocked"), json.dumps(msg_completed)) ] # Pre-test scaffolding. Hard-code some mocked out # attributes/variables because we're skipping the usual # initialization steps. f.conn = mock.Mock(pika.connection.Connection) publish = mock.Mock() channel = mock.Mock() channel.consume.return_value = iter(consume_iter) channel.basic_publish = publish f.ch = channel f.active_sequence = {'hosts': ['localhost']} f.group = 'testgroup' f.dynamic = {} f.active_step = new_notify_step('failed') f.post_deploy_action = [ { "NAME": "Update dates", "COMMAND": "servicenow", "SUBCOMMAND": "updatedates", "PARAMETERS": { "foo": "bar" } } ] with mock.patch('recore.amqp.MQ_CONF') as mq_conf: mq_conf = MQ_CONF set_field = mock.MagicMock() filter = mock.MagicMock(return_value=set_field) f.filter = filter self.assertEqual(f._post_deploy_action(), True)
def test_step_notification_started(self, send_notification, on_started, dequeue_step, setup): """Per-step notifications work when starting a step Tests for the case where only one notification transport (irc, email, etc) is defined""" f = FSM(TEST_PBID, state_id) msg_started = {'status': 'started'} consume_iter = [ (mock.Mock(name="method_mocked"), mock.Mock(name="properties_mocked"), json.dumps(msg_started)) ] # Pre-test scaffolding. Hard-code some mocked out # attributes/variables because we're skipping the usual # initialization steps. f.conn = mock.Mock(pika.connection.Connection) publish = mock.Mock() channel = mock.Mock() channel.consume.return_value = iter(consume_iter) channel.basic_publish = publish f.ch = channel f.active_sequence = {'hosts': ['localhost']} f.group = 'testgroup' f.dynamic = {} f.active_step = new_notify_step('started') # Run the method now. It should terminate when it reaches the # end of _run() with a call to a mocked out on_started() with mock.patch('recore.amqp.MQ_CONF') as mq_conf: mq_conf = MQ_CONF set_field = mock.MagicMock() filter = mock.MagicMock(return_value=set_field) f.filter = filter f._run() self.assertEqual(send_notification.call_count, 1) self.assertEqual(send_notification.call_args[0][1], 'notify.irc') self.assertEqual(send_notification.call_args[0][2], state_id) self.assertEqual(send_notification.call_args[0][3], ['#achannel']) self.assertEqual(send_notification.call_args[0][4], 'started')
def test_on_started(self, ended, pdc): """Once started, the FSM waits for a response, and then calls on_ended""" pdc.return_value = True with nested( mock.patch('recore.mongo.lookup_state'), mock.patch('recore.mongo.database') ) as (lookup_state, database): lookup_state.return_value = _state.copy() # { # 'group': 'PROJECT', # 'dynamic': {}, # 'completed_steps': [], # 'active_step': 'active_step', # 'remaining_steps': [], # } f = FSM(TEST_PBID, state_id) f.reply_queue = temp_queue f.group = 'GROUP' consume_iter = [ (mock.Mock(name="method_mocked"), mock.Mock(name="properties_mocked"), json.dumps(msg_started)) ] publish = mock.Mock() channel = mock.Mock() channel.consume.return_value = iter(consume_iter) channel.basic_publish = publish f.ch = channel f.conn = mock.Mock(pika.connection.Connection) set_field = mock.MagicMock() filter = mock.MagicMock(return_value=set_field) f.filter = filter f._setup() f.on_started(f.ch, *consume_iter[0]) f.ch.basic_ack.assert_called_once_with(consume_iter[0][0].delivery_tag) f.ch.cancel.assert_called_once_with() f.on_ended.assert_called_once_with(f.ch, *consume_iter[0])
def test_step_notification_failed_before_started_received(self, send_notification, move_active, run, skipped): """Per-step notifications happen if a step fails when the worker attempts to start it""" f = FSM(state_id) msg_failed = {'status': 'failed'} consume_iter = [ (mock.Mock(name="method_mocked"), mock.Mock(name="properties_mocked"), json.dumps(msg_failed)) ] # Pre-test scaffolding. Hard-code some mocked out # attributes/variables because we're skipping the usual # initialization steps. f.conn = mock.Mock(pika.connection.Connection) publish = mock.Mock() channel = mock.Mock() channel.consume.return_value = iter(consume_iter) channel.basic_publish = publish f.ch = channel f.active_sequence = {'hosts': ['localhost']} f.group = 'testgroup' f.dynamic = {} f.active_step = new_notify_step('failed') # Run the ended method with a body having 'status' as completed f.on_started(channel, mock.Mock(name="method_mocked"), mock.Mock(name="header_mocked"), json.dumps(msg_failed)) self.assertEqual(send_notification.call_count, 1) self.assertEqual(send_notification.call_args[0][1], 'notify.irc') self.assertEqual(send_notification.call_args[0][2], state_id) self.assertEqual(send_notification.call_args[0][3], ['#achannel']) self.assertEqual(send_notification.call_args[0][4], 'failed')