mirror of
https://github.com/ansible/awx.git
synced 2024-11-01 16:51:11 +03:00
Merge pull request #1257 from benthomasson/network_ui_unit_tests
Adds unit tests for network_ui
This commit is contained in:
commit
e5dd3a9626
5
Makefile
5
Makefile
@ -372,7 +372,8 @@ awx-link:
|
||||
sed -i "s/placeholder/$(shell git describe --long | sed 's/\./\\./g')/" /awx_devel/awx.egg-info/PKG-INFO
|
||||
cp /tmp/awx.egg-link /venv/awx/lib/python2.7/site-packages/awx.egg-link
|
||||
|
||||
TEST_DIRS ?= awx/main/tests/unit awx/main/tests/functional awx/conf/tests awx/sso/tests
|
||||
TEST_DIRS ?= awx/main/tests/unit awx/main/tests/functional awx/conf/tests awx/sso/tests awx/network_ui/tests/unit
|
||||
|
||||
# Run all API unit tests.
|
||||
test:
|
||||
@if [ "$(VENV_BASE)" ]; then \
|
||||
@ -386,7 +387,7 @@ test_unit:
|
||||
@if [ "$(VENV_BASE)" ]; then \
|
||||
. $(VENV_BASE)/awx/bin/activate; \
|
||||
fi; \
|
||||
py.test awx/main/tests/unit awx/conf/tests/unit awx/sso/tests/unit
|
||||
py.test awx/main/tests/unit awx/conf/tests/unit awx/sso/tests/unit awx/network_ui/tests/unit
|
||||
|
||||
test_ansible:
|
||||
@if [ "$(VENV_BASE)" ]; then \
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Copyright (c) 2017 Red Hat, Inc
|
||||
from channels import Group
|
||||
import channels
|
||||
from channels.auth import channel_session_user, channel_session_user_from_http
|
||||
from awx.network_ui.models import Topology, Device, Link, Client, Interface
|
||||
from awx.network_ui.models import TopologyInventory
|
||||
@ -22,6 +22,10 @@ def parse_inventory_id(data):
|
||||
inventory_id = int(inventory_id[0])
|
||||
except ValueError:
|
||||
inventory_id = None
|
||||
except IndexError:
|
||||
inventory_id = None
|
||||
except TypeError:
|
||||
inventory_id = None
|
||||
if not inventory_id:
|
||||
inventory_id = None
|
||||
return inventory_id
|
||||
@ -42,10 +46,10 @@ class NetworkingEvents(object):
|
||||
message_type = data.pop(0)
|
||||
message_value = data.pop(0)
|
||||
if isinstance(message_value, list):
|
||||
logger.error("Message has no sender")
|
||||
logger.warning("Message has no sender")
|
||||
return None, None
|
||||
if isinstance(message_value, dict) and client_id != message_value.get('sender'):
|
||||
logger.error("client_id mismatch expected: %s actual %s", client_id, message_value.get('sender'))
|
||||
logger.warning("client_id mismatch expected: %s actual %s", client_id, message_value.get('sender'))
|
||||
return None, None
|
||||
return message_type, message_value
|
||||
else:
|
||||
@ -58,11 +62,19 @@ class NetworkingEvents(object):
|
||||
of name onX where X is the message type.
|
||||
'''
|
||||
topology_id = message.get('topology')
|
||||
assert topology_id is not None, "No topology_id"
|
||||
if topology_id is None:
|
||||
logger.warning("Unsupported message %s: no topology", message)
|
||||
return
|
||||
client_id = message.get('client')
|
||||
assert client_id is not None, "No client_id"
|
||||
if client_id is None:
|
||||
logger.warning("Unsupported message %s: no client", message)
|
||||
return
|
||||
if 'text' not in message:
|
||||
logger.warning("Unsupported message %s: no data", message)
|
||||
return
|
||||
message_type, message_value = self.parse_message_text(message['text'], client_id)
|
||||
if message_type is None:
|
||||
logger.warning("Unsupported message %s: no message type", message)
|
||||
return
|
||||
handler = self.get_handler(message_type)
|
||||
if handler is not None:
|
||||
@ -98,9 +110,6 @@ class NetworkingEvents(object):
|
||||
def onDeviceMove(self, device, topology_id, client_id):
|
||||
Device.objects.filter(topology_id=topology_id, cid=device['id']).update(x=device['x'], y=device['y'])
|
||||
|
||||
def onDeviceInventoryUpdate(self, device, topology_id, client_id):
|
||||
Device.objects.filter(topology_id=topology_id, cid=device['id']).update(host_id=device['host_id'])
|
||||
|
||||
def onDeviceLabelEdit(self, device, topology_id, client_id):
|
||||
logger.debug("Device label edited %s", device)
|
||||
Device.objects.filter(topology_id=topology_id, cid=device['id']).update(name=device['name'])
|
||||
@ -132,6 +141,12 @@ class NetworkingEvents(object):
|
||||
device_map = dict(Device.objects
|
||||
.filter(topology_id=topology_id, cid__in=[link['from_device_id'], link['to_device_id']])
|
||||
.values_list('cid', 'pk'))
|
||||
if link['from_device_id'] not in device_map:
|
||||
logger.warning('Device not found')
|
||||
return
|
||||
if link['to_device_id'] not in device_map:
|
||||
logger.warning('Device not found')
|
||||
return
|
||||
Link.objects.get_or_create(cid=link['id'],
|
||||
name=link['name'],
|
||||
from_device_id=device_map[link['from_device_id']],
|
||||
@ -150,8 +165,10 @@ class NetworkingEvents(object):
|
||||
.filter(topology_id=topology_id, cid__in=[link['from_device_id'], link['to_device_id']])
|
||||
.values_list('cid', 'pk'))
|
||||
if link['from_device_id'] not in device_map:
|
||||
logger.warning('Device not found')
|
||||
return
|
||||
if link['to_device_id'] not in device_map:
|
||||
logger.warning('Device not found')
|
||||
return
|
||||
Link.objects.filter(cid=link['id'],
|
||||
from_device_id=device_map[link['from_device_id']],
|
||||
@ -212,11 +229,11 @@ def ws_connect(message):
|
||||
TopologyInventory(inventory_id=inventory_id, topology_id=topology.pk).save()
|
||||
topology_id = topology.pk
|
||||
message.channel_session['topology_id'] = topology_id
|
||||
Group("topology-%s" % topology_id).add(message.reply_channel)
|
||||
channels.Group("topology-%s" % topology_id).add(message.reply_channel)
|
||||
client = Client()
|
||||
client.save()
|
||||
message.channel_session['client_id'] = client.pk
|
||||
Group("client-%s" % client.pk).add(message.reply_channel)
|
||||
channels.Group("client-%s" % client.pk).add(message.reply_channel)
|
||||
message.reply_channel.send({"text": json.dumps(["id", client.pk])})
|
||||
message.reply_channel.send({"text": json.dumps(["topology_id", topology_id])})
|
||||
topology_data = transform_dict(dict(id='topology_id',
|
||||
@ -278,7 +295,7 @@ def send_snapshot(channel, topology_id):
|
||||
@channel_session_user
|
||||
def ws_message(message):
|
||||
# Send to all clients editing the topology
|
||||
Group("topology-%s" % message.channel_session['topology_id']).send({"text": message['text']})
|
||||
channels.Group("topology-%s" % message.channel_session['topology_id']).send({"text": message['text']})
|
||||
# Send to networking_events handler
|
||||
networking_events_dispatcher.handle({"text": message['text'],
|
||||
"topology": message.channel_session['topology_id'],
|
||||
@ -288,5 +305,5 @@ def ws_message(message):
|
||||
@channel_session_user
|
||||
def ws_disconnect(message):
|
||||
if 'topology_id' in message.channel_session:
|
||||
Group("topology-%s" % message.channel_session['topology_id']).discard(message.reply_channel)
|
||||
channels.Group("topology-%s" % message.channel_session['topology_id']).discard(message.reply_channel)
|
||||
|
||||
|
0
awx/network_ui/tests/__init__.py
Normal file
0
awx/network_ui/tests/__init__.py
Normal file
0
awx/network_ui/tests/unit/__init__.py
Normal file
0
awx/network_ui/tests/unit/__init__.py
Normal file
240
awx/network_ui/tests/unit/test_consumers.py
Normal file
240
awx/network_ui/tests/unit/test_consumers.py
Normal file
@ -0,0 +1,240 @@
|
||||
|
||||
import mock
|
||||
import logging
|
||||
import json
|
||||
import imp
|
||||
from mock import patch
|
||||
patch('channels.auth.channel_session_user', lambda x: x).start()
|
||||
patch('channels.auth.channel_session_user_from_http', lambda x: x).start()
|
||||
|
||||
from awx.network_ui.consumers import parse_inventory_id, networking_events_dispatcher, send_snapshot # noqa
|
||||
from awx.network_ui.models import Topology, Device, Link, Interface, TopologyInventory, Client # noqa
|
||||
import awx # noqa
|
||||
import awx.network_ui # noqa
|
||||
import awx.network_ui.consumers # noqa
|
||||
imp.reload(awx.network_ui.consumers)
|
||||
|
||||
|
||||
def test_parse_inventory_id():
|
||||
assert parse_inventory_id({}) is None
|
||||
assert parse_inventory_id({'inventory_id': ['1']}) == 1
|
||||
assert parse_inventory_id({'inventory_id': ['0']}) is None
|
||||
assert parse_inventory_id({'inventory_id': ['X']}) is None
|
||||
assert parse_inventory_id({'inventory_id': []}) is None
|
||||
assert parse_inventory_id({'inventory_id': 'x'}) is None
|
||||
assert parse_inventory_id({'inventory_id': '12345'}) == 1
|
||||
assert parse_inventory_id({'inventory_id': 1}) is None
|
||||
|
||||
|
||||
def test_network_events_handle_message_incomplete_message1():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
with mock.patch.object(logger, 'warning') as log_mock:
|
||||
networking_events_dispatcher.handle({})
|
||||
log_mock.assert_called_once_with(
|
||||
'Unsupported message %s: no topology', {})
|
||||
|
||||
|
||||
def test_network_events_handle_message_incomplete_message2():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
with mock.patch.object(logger, 'warning') as log_mock:
|
||||
networking_events_dispatcher.handle({'topology': [0]})
|
||||
log_mock.assert_called_once_with(
|
||||
'Unsupported message %s: no client', {'topology': [0]})
|
||||
|
||||
|
||||
def test_network_events_handle_message_incomplete_message3():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
with mock.patch.object(logger, 'warning') as log_mock:
|
||||
networking_events_dispatcher.handle({'topology': [1]})
|
||||
log_mock.assert_called_once_with(
|
||||
'Unsupported message %s: no client', {'topology': [1]})
|
||||
|
||||
|
||||
def test_network_events_handle_message_incomplete_message4():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
with mock.patch.object(logger, 'warning') as log_mock:
|
||||
networking_events_dispatcher.handle({'topology': 1, 'client': 1})
|
||||
log_mock.assert_called_once_with('Unsupported message %s: no data', {
|
||||
'client': 1, 'topology': 1})
|
||||
|
||||
|
||||
def test_network_events_handle_message_incomplete_message5():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
with mock.patch.object(logger, 'warning') as log_mock:
|
||||
message = ['DeviceCreate']
|
||||
networking_events_dispatcher.handle(
|
||||
{'topology': 1, 'client': 1, 'text': json.dumps(message)})
|
||||
log_mock.assert_called_once_with('Unsupported message %s: no message type', {
|
||||
'text': '["DeviceCreate"]', 'client': 1, 'topology': 1})
|
||||
|
||||
|
||||
def test_network_events_handle_message_incomplete_message6():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
with mock.patch.object(logger, 'warning') as log_mock:
|
||||
message = ['DeviceCreate', []]
|
||||
networking_events_dispatcher.handle(
|
||||
{'topology': 1, 'client': 1, 'text': json.dumps(message)})
|
||||
log_mock.assert_has_calls([
|
||||
mock.call('Message has no sender'),
|
||||
mock.call('Unsupported message %s: no message type', {'text': '["DeviceCreate", []]', 'client': 1, 'topology': 1})])
|
||||
|
||||
|
||||
def test_network_events_handle_message_incomplete_message7():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
with mock.patch.object(logger, 'warning') as log_mock:
|
||||
message = ['DeviceCreate', {}]
|
||||
networking_events_dispatcher.handle(
|
||||
{'topology': 1, 'client': 1, 'text': json.dumps(message)})
|
||||
log_mock.assert_has_calls([
|
||||
mock.call('client_id mismatch expected: %s actual %s', 1, None),
|
||||
mock.call('Unsupported message %s: no message type', {'text': '["DeviceCreate", {}]', 'client': 1, 'topology': 1})])
|
||||
|
||||
|
||||
def test_network_events_handle_message_incomplete_message8():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
with mock.patch.object(logger, 'warning') as log_mock:
|
||||
message = ['Unsupported', {'sender': 1}]
|
||||
networking_events_dispatcher.handle(
|
||||
{'topology': 1, 'client': 1, 'text': json.dumps(message)})
|
||||
log_mock.assert_called_once_with(
|
||||
'Unsupported message %s: no handler', u'Unsupported')
|
||||
|
||||
|
||||
def test_send_snapshot_empty():
|
||||
channel = mock.MagicMock()
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
with mock.patch.object(logger, 'warning') as log_mock,\
|
||||
mock.patch.object(Device, 'objects'),\
|
||||
mock.patch.object(Link, 'objects'),\
|
||||
mock.patch.object(Interface, 'objects'),\
|
||||
mock.patch.object(Topology, 'objects'):
|
||||
send_snapshot(channel, 1)
|
||||
log_mock.assert_not_called()
|
||||
channel.send.assert_called_once_with(
|
||||
{'text': '["Snapshot", {"links": [], "devices": [], "sender": 0}]'})
|
||||
|
||||
|
||||
def test_send_snapshot_single():
|
||||
channel = mock.MagicMock()
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
with mock.patch.object(logger, 'warning') as log_mock,\
|
||||
mock.patch.object(Device, 'objects') as device_objects_mock,\
|
||||
mock.patch.object(Link, 'objects'),\
|
||||
mock.patch.object(Interface, 'objects') as interface_objects_mock:
|
||||
|
||||
interface_objects_mock.filter.return_value.values.return_value = [
|
||||
dict(cid=1, device_id=1, id=1, name="eth0")]
|
||||
device_objects_mock.filter.return_value.values.return_value = [
|
||||
dict(cid=1, id=1, device_type="host", name="host1", x=0, y=0,
|
||||
interface_id_seq=1, host_id=1)]
|
||||
send_snapshot(channel, 1)
|
||||
device_objects_mock.filter.assert_called_once_with(topology_id=1)
|
||||
device_objects_mock.filter.return_value.values.assert_called_once_with()
|
||||
interface_objects_mock.filter.assert_called_once_with(
|
||||
device__topology_id=1)
|
||||
interface_objects_mock.filter.return_value.values.assert_called_once_with()
|
||||
log_mock.assert_not_called()
|
||||
channel.send.assert_called_once_with(
|
||||
{'text': '''["Snapshot", {"links": [], "devices": [{"interface_id_seq": 1, \
|
||||
"name": "host1", "interfaces": [{"id": 1, "device_id": 1, "name": "eth0", "interface_id": 1}], \
|
||||
"device_type": "host", "host_id": 1, "y": 0, "x": 0, "id": 1, "device_id": 1}], "sender": 0}]'''})
|
||||
|
||||
|
||||
def test_ws_disconnect():
|
||||
message = mock.MagicMock()
|
||||
message.channel_session = dict(topology_id=1)
|
||||
message.reply_channel = 'foo'
|
||||
with mock.patch('channels.Group') as group_mock:
|
||||
awx.network_ui.consumers.ws_disconnect(message)
|
||||
group_mock.assert_called_once_with('topology-1')
|
||||
group_mock.return_value.discard.assert_called_once_with('foo')
|
||||
|
||||
|
||||
def test_ws_disconnect_no_topology():
|
||||
message = mock.MagicMock()
|
||||
with mock.patch('channels.Group') as group_mock:
|
||||
awx.network_ui.consumers.ws_disconnect(message)
|
||||
group_mock.assert_not_called()
|
||||
|
||||
|
||||
def test_ws_message():
|
||||
message = mock.MagicMock()
|
||||
message.channel_session = dict(topology_id=1, client_id=1)
|
||||
message.__getitem__.return_value = json.dumps([])
|
||||
print (message['text'])
|
||||
with mock.patch('channels.Group') as group_mock:
|
||||
awx.network_ui.consumers.ws_message(message)
|
||||
group_mock.assert_called_once_with('topology-1')
|
||||
group_mock.return_value.send.assert_called_once_with({'text': '[]'})
|
||||
|
||||
|
||||
def test_ws_connect_unauthenticated():
|
||||
message = mock.MagicMock()
|
||||
message.user.is_authenticated.return_value = False
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
with mock.patch.object(logger, 'error') as log_mock:
|
||||
awx.network_ui.consumers.ws_connect(message)
|
||||
log_mock.assert_called_once_with('Request user is not authenticated to use websocket.')
|
||||
|
||||
|
||||
def test_ws_connect_new_topology():
|
||||
message = mock.MagicMock()
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
with mock.patch('awx.network_ui.consumers.Client') as client_mock,\
|
||||
mock.patch('awx.network_ui.consumers.Topology') as topology_mock,\
|
||||
mock.patch('channels.Group'),\
|
||||
mock.patch('awx.network_ui.consumers.send_snapshot') as send_snapshot_mock,\
|
||||
mock.patch.object(logger, 'warning'),\
|
||||
mock.patch.object(TopologyInventory, 'objects'),\
|
||||
mock.patch.object(TopologyInventory, 'save'),\
|
||||
mock.patch.object(Topology, 'save'),\
|
||||
mock.patch.object(Topology, 'objects'),\
|
||||
mock.patch.object(Device, 'objects'),\
|
||||
mock.patch.object(Link, 'objects'),\
|
||||
mock.patch.object(Interface, 'objects'):
|
||||
client_mock.return_value.pk = 777
|
||||
topology_mock.return_value = Topology(
|
||||
name="topology", scale=1.0, panX=0, panY=0, pk=999)
|
||||
awx.network_ui.consumers.ws_connect(message)
|
||||
message.reply_channel.send.assert_has_calls([
|
||||
mock.call({'text': '["id", 777]'}),
|
||||
mock.call({'text': '["topology_id", 999]'}),
|
||||
mock.call(
|
||||
{'text': '["Topology", {"scale": 1.0, "name": "topology", "device_id_seq": 0, "panY": 0, "panX": 0, "topology_id": 999, "link_id_seq": 0}]'}),
|
||||
])
|
||||
send_snapshot_mock.assert_called_once_with(message.reply_channel, 999)
|
||||
|
||||
|
||||
def test_ws_connect_existing_topology():
|
||||
message = mock.MagicMock()
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
with mock.patch('awx.network_ui.consumers.Client') as client_mock,\
|
||||
mock.patch('awx.network_ui.consumers.send_snapshot') as send_snapshot_mock,\
|
||||
mock.patch('channels.Group'),\
|
||||
mock.patch.object(logger, 'warning'),\
|
||||
mock.patch.object(TopologyInventory, 'objects') as topology_inventory_objects_mock,\
|
||||
mock.patch.object(TopologyInventory, 'save'),\
|
||||
mock.patch.object(Topology, 'save'),\
|
||||
mock.patch.object(Topology, 'objects') as topology_objects_mock,\
|
||||
mock.patch.object(Device, 'objects'),\
|
||||
mock.patch.object(Link, 'objects'),\
|
||||
mock.patch.object(Interface, 'objects'):
|
||||
topology_inventory_objects_mock.filter.return_value.values_list.return_value = [
|
||||
1]
|
||||
client_mock.return_value.pk = 888
|
||||
topology_objects_mock.get.return_value = Topology(pk=1001,
|
||||
id=1,
|
||||
name="topo",
|
||||
panX=0,
|
||||
panY=0,
|
||||
scale=1.0,
|
||||
link_id_seq=1,
|
||||
device_id_seq=1)
|
||||
awx.network_ui.consumers.ws_connect(message)
|
||||
message.reply_channel.send.assert_has_calls([
|
||||
mock.call({'text': '["id", 888]'}),
|
||||
mock.call({'text': '["topology_id", 1001]'}),
|
||||
mock.call(
|
||||
{'text': '["Topology", {"scale": 1.0, "name": "topo", "device_id_seq": 1, "panY": 0, "panX": 0, "topology_id": 1001, "link_id_seq": 1}]'}),
|
||||
])
|
||||
send_snapshot_mock.assert_called_once_with(message.reply_channel, 1001)
|
15
awx/network_ui/tests/unit/test_models.py
Normal file
15
awx/network_ui/tests/unit/test_models.py
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
|
||||
from awx.network_ui.models import Device, Topology, Interface
|
||||
|
||||
|
||||
def test_device():
|
||||
assert str(Device(name="foo")) == "foo"
|
||||
|
||||
|
||||
def test_topology():
|
||||
assert str(Topology(name="foo")) == "foo"
|
||||
|
||||
|
||||
def test_interface():
|
||||
assert str(Interface(name="foo")) == "foo"
|
451
awx/network_ui/tests/unit/test_network_events.py
Normal file
451
awx/network_ui/tests/unit/test_network_events.py
Normal file
@ -0,0 +1,451 @@
|
||||
import mock
|
||||
import json
|
||||
import logging
|
||||
|
||||
from awx.network_ui.consumers import networking_events_dispatcher
|
||||
from awx.network_ui.models import Topology, Device, Link, Interface
|
||||
|
||||
|
||||
def message(message):
|
||||
def wrapper(fn):
|
||||
fn.tests_message = message
|
||||
return fn
|
||||
return wrapper
|
||||
|
||||
|
||||
@message('DeviceMove')
|
||||
def test_network_events_handle_message_DeviceMove():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['DeviceMove', dict(
|
||||
msg_type='DeviceMove',
|
||||
sender=1,
|
||||
id=1,
|
||||
x=100,
|
||||
y=100,
|
||||
previous_x=0,
|
||||
previous_y=0
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock,\
|
||||
mock.patch.object(Device, 'objects') as device_objects_mock:
|
||||
networking_events_dispatcher.handle(message)
|
||||
device_objects_mock.filter.assert_called_once_with(
|
||||
cid=1, topology_id=1)
|
||||
device_objects_mock.filter.return_value.update.assert_called_once_with(
|
||||
x=100, y=100)
|
||||
log_mock.assert_not_called()
|
||||
|
||||
|
||||
@message('DeviceCreate')
|
||||
def test_network_events_handle_message_DeviceCreate():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['DeviceCreate', dict(msg_type='DeviceCreate',
|
||||
sender=1,
|
||||
id=1,
|
||||
x=0,
|
||||
y=0,
|
||||
name="test_created",
|
||||
type='host',
|
||||
host_id=None)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
|
||||
with mock.patch.object(logger, 'warning') as log_mock,\
|
||||
mock.patch.object(Topology.objects, 'filter') as topology_objects_mock,\
|
||||
mock.patch.object(Device.objects, 'get_or_create') as device_objects_mock:
|
||||
device_mock = mock.MagicMock()
|
||||
filter_mock = mock.MagicMock()
|
||||
device_objects_mock.return_value = [device_mock, True]
|
||||
topology_objects_mock.return_value = filter_mock
|
||||
networking_events_dispatcher.handle(message)
|
||||
device_objects_mock.assert_called_once_with(
|
||||
cid=1,
|
||||
defaults={'name': u'test_created', 'cid': 1, 'device_type': u'host',
|
||||
'x': 0, 'y': 0, 'host_id': None},
|
||||
topology_id=1)
|
||||
device_mock.save.assert_called_once_with()
|
||||
topology_objects_mock.assert_called_once_with(
|
||||
device_id_seq__lt=1, pk=1)
|
||||
filter_mock.update.assert_called_once_with(device_id_seq=1)
|
||||
log_mock.assert_not_called()
|
||||
|
||||
|
||||
@message('DeviceLabelEdit')
|
||||
def test_network_events_handle_message_DeviceLabelEdit():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['DeviceLabelEdit', dict(
|
||||
msg_type='DeviceLabelEdit',
|
||||
sender=1,
|
||||
id=1,
|
||||
name='test_changed',
|
||||
previous_name='test_created'
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock,\
|
||||
mock.patch.object(Device.objects, 'filter') as device_objects_filter_mock:
|
||||
networking_events_dispatcher.handle(message)
|
||||
device_objects_filter_mock.assert_called_once_with(
|
||||
cid=1, topology_id=1)
|
||||
log_mock.assert_not_called()
|
||||
|
||||
|
||||
@message('DeviceSelected')
|
||||
def test_network_events_handle_message_DeviceSelected():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['DeviceSelected', dict(
|
||||
msg_type='DeviceSelected',
|
||||
sender=1,
|
||||
id=1
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock:
|
||||
networking_events_dispatcher.handle(message)
|
||||
log_mock.assert_not_called()
|
||||
|
||||
|
||||
@message('DeviceUnSelected')
|
||||
def test_network_events_handle_message_DeviceUnSelected():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['DeviceUnSelected', dict(
|
||||
msg_type='DeviceUnSelected',
|
||||
sender=1,
|
||||
id=1
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock:
|
||||
networking_events_dispatcher.handle(message)
|
||||
log_mock.assert_not_called()
|
||||
|
||||
|
||||
@message('DeviceDestroy')
|
||||
def test_network_events_handle_message_DeviceDestory():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['DeviceDestroy', dict(
|
||||
msg_type='DeviceDestroy',
|
||||
sender=1,
|
||||
id=1,
|
||||
previous_x=0,
|
||||
previous_y=0,
|
||||
previous_name="",
|
||||
previous_type="host",
|
||||
previous_host_id="1")]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock,\
|
||||
mock.patch.object(Device, 'objects') as device_objects_mock:
|
||||
networking_events_dispatcher.handle(message)
|
||||
device_objects_mock.filter.assert_called_once_with(
|
||||
cid=1, topology_id=1)
|
||||
device_objects_mock.filter.return_value.delete.assert_called_once_with()
|
||||
log_mock.assert_not_called()
|
||||
|
||||
|
||||
@message('InterfaceCreate')
|
||||
def test_network_events_handle_message_InterfaceCreate():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['InterfaceCreate', dict(
|
||||
msg_type='InterfaceCreate',
|
||||
sender=1,
|
||||
device_id=1,
|
||||
id=1,
|
||||
name='eth0'
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock,\
|
||||
mock.patch.object(Device, 'objects') as device_objects_mock,\
|
||||
mock.patch.object(Interface, 'objects') as interface_objects_mock:
|
||||
device_objects_mock.get.return_value.pk = 99
|
||||
networking_events_dispatcher.handle(message)
|
||||
device_objects_mock.get.assert_called_once_with(cid=1, topology_id=1)
|
||||
device_objects_mock.filter.assert_called_once_with(
|
||||
cid=1, interface_id_seq__lt=1, topology_id=1)
|
||||
interface_objects_mock.get_or_create.assert_called_once_with(
|
||||
cid=1, defaults={'name': u'eth0'}, device_id=99)
|
||||
log_mock.assert_not_called()
|
||||
|
||||
|
||||
@message('InterfaceLabelEdit')
|
||||
def test_network_events_handle_message_InterfaceLabelEdit():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['InterfaceLabelEdit', dict(
|
||||
msg_type='InterfaceLabelEdit',
|
||||
sender=1,
|
||||
id=1,
|
||||
device_id=1,
|
||||
name='new name',
|
||||
previous_name='old name'
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock,\
|
||||
mock.patch.object(Interface, 'objects') as interface_objects_mock:
|
||||
networking_events_dispatcher.handle(message)
|
||||
interface_objects_mock.filter.assert_called_once_with(
|
||||
cid=1, device__cid=1, device__topology_id=1)
|
||||
interface_objects_mock.filter.return_value.update.assert_called_once_with(
|
||||
name=u'new name')
|
||||
log_mock.assert_not_called()
|
||||
|
||||
|
||||
@message('LinkLabelEdit')
|
||||
def test_network_events_handle_message_LinkLabelEdit():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['LinkLabelEdit', dict(
|
||||
msg_type='LinkLabelEdit',
|
||||
sender=1,
|
||||
id=1,
|
||||
name='new name',
|
||||
previous_name='old name'
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock,\
|
||||
mock.patch.object(Link, 'objects') as link_objects_mock:
|
||||
networking_events_dispatcher.handle(message)
|
||||
link_objects_mock.filter.assert_called_once_with(
|
||||
cid=1, from_device__topology_id=1)
|
||||
link_objects_mock.filter.return_value.update.assert_called_once_with(
|
||||
name=u'new name')
|
||||
log_mock.assert_not_called()
|
||||
|
||||
|
||||
@message('LinkCreate')
|
||||
def test_network_events_handle_message_LinkCreate():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['LinkCreate', dict(
|
||||
msg_type='LinkCreate',
|
||||
id=1,
|
||||
sender=1,
|
||||
name="",
|
||||
from_device_id=1,
|
||||
to_device_id=2,
|
||||
from_interface_id=1,
|
||||
to_interface_id=1
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock,\
|
||||
mock.patch.object(Device, 'objects') as device_objects_mock,\
|
||||
mock.patch.object(Link, 'objects') as link_objects_mock,\
|
||||
mock.patch.object(Interface, 'objects') as interface_objects_mock,\
|
||||
mock.patch.object(Topology, 'objects') as topology_objects_mock:
|
||||
values_list_mock = mock.MagicMock()
|
||||
values_list_mock.values_list.return_value = [(1,1), (2,2)]
|
||||
interface_objects_mock.get.return_value = mock.MagicMock()
|
||||
interface_objects_mock.get.return_value.pk = 7
|
||||
device_objects_mock.filter.return_value = values_list_mock
|
||||
topology_objects_mock.filter.return_value = mock.MagicMock()
|
||||
networking_events_dispatcher.handle(message)
|
||||
device_objects_mock.filter.assert_called_once_with(
|
||||
cid__in=[1, 2], topology_id=1)
|
||||
values_list_mock.values_list.assert_called_once_with('cid', 'pk')
|
||||
link_objects_mock.get_or_create.assert_called_once_with(
|
||||
cid=1, from_device_id=1, from_interface_id=7, name=u'',
|
||||
to_device_id=2, to_interface_id=7)
|
||||
topology_objects_mock.filter.assert_called_once_with(
|
||||
link_id_seq__lt=1, pk=1)
|
||||
topology_objects_mock.filter.return_value.update.assert_called_once_with(
|
||||
link_id_seq=1)
|
||||
log_mock.assert_not_called()
|
||||
|
||||
|
||||
@message('LinkCreate')
|
||||
def test_network_events_handle_message_LinkCreate_bad_device1():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['LinkCreate', dict(
|
||||
msg_type='LinkCreate',
|
||||
id=1,
|
||||
sender=1,
|
||||
name="",
|
||||
from_device_id=1,
|
||||
to_device_id=2,
|
||||
from_interface_id=1,
|
||||
to_interface_id=1
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock,\
|
||||
mock.patch.object(Device, 'objects') as device_objects_mock,\
|
||||
mock.patch.object(Link, 'objects'),\
|
||||
mock.patch.object(Interface, 'objects') as interface_objects_mock,\
|
||||
mock.patch.object(Topology, 'objects') as topology_objects_mock:
|
||||
values_list_mock = mock.MagicMock()
|
||||
values_list_mock.values_list.return_value = [(9,1), (2,2)]
|
||||
interface_objects_mock.get.return_value = mock.MagicMock()
|
||||
interface_objects_mock.get.return_value.pk = 7
|
||||
device_objects_mock.filter.return_value = values_list_mock
|
||||
topology_objects_mock.filter.return_value = mock.MagicMock()
|
||||
networking_events_dispatcher.handle(message)
|
||||
device_objects_mock.filter.assert_called_once_with(
|
||||
cid__in=[1, 2], topology_id=1)
|
||||
values_list_mock.values_list.assert_called_once_with('cid', 'pk')
|
||||
log_mock.assert_called_once_with('Device not found')
|
||||
|
||||
|
||||
@message('LinkCreate')
|
||||
def test_network_events_handle_message_LinkCreate_bad_device2():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['LinkCreate', dict(
|
||||
msg_type='LinkCreate',
|
||||
id=1,
|
||||
sender=1,
|
||||
name="",
|
||||
from_device_id=1,
|
||||
to_device_id=2,
|
||||
from_interface_id=1,
|
||||
to_interface_id=1
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock,\
|
||||
mock.patch.object(Device, 'objects') as device_objects_mock,\
|
||||
mock.patch.object(Link, 'objects'),\
|
||||
mock.patch.object(Interface, 'objects') as interface_objects_mock,\
|
||||
mock.patch.object(Topology, 'objects') as topology_objects_mock:
|
||||
values_list_mock = mock.MagicMock()
|
||||
values_list_mock.values_list.return_value = [(1,1), (9,2)]
|
||||
interface_objects_mock.get.return_value = mock.MagicMock()
|
||||
interface_objects_mock.get.return_value.pk = 7
|
||||
device_objects_mock.filter.return_value = values_list_mock
|
||||
topology_objects_mock.filter.return_value = mock.MagicMock()
|
||||
networking_events_dispatcher.handle(message)
|
||||
device_objects_mock.filter.assert_called_once_with(
|
||||
cid__in=[1, 2], topology_id=1)
|
||||
values_list_mock.values_list.assert_called_once_with('cid', 'pk')
|
||||
log_mock.assert_called_once_with('Device not found')
|
||||
|
||||
|
||||
@message('LinkDestroy')
|
||||
def test_network_events_handle_message_LinkDestroy():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['LinkDestroy', dict(
|
||||
msg_type='LinkDestroy',
|
||||
id=1,
|
||||
sender=1,
|
||||
name="",
|
||||
from_device_id=1,
|
||||
to_device_id=2,
|
||||
from_interface_id=1,
|
||||
to_interface_id=1
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock,\
|
||||
mock.patch.object(Device.objects, 'filter') as device_filter_mock,\
|
||||
mock.patch.object(Link.objects, 'filter') as link_filter_mock,\
|
||||
mock.patch.object(Interface.objects, 'get') as interface_get_mock:
|
||||
values_mock = mock.MagicMock()
|
||||
interface_get_mock.return_value = mock.MagicMock()
|
||||
interface_get_mock.return_value.pk = 7
|
||||
device_filter_mock.return_value = values_mock
|
||||
values_mock.values_list.return_value = [(1,1), (2,2)]
|
||||
networking_events_dispatcher.handle(message)
|
||||
device_filter_mock.assert_called_once_with(
|
||||
cid__in=[1, 2], topology_id=1)
|
||||
values_mock.values_list.assert_called_once_with('cid', 'pk')
|
||||
link_filter_mock.assert_called_once_with(
|
||||
cid=1, from_device_id=1, from_interface_id=7, to_device_id=2, to_interface_id=7)
|
||||
log_mock.assert_not_called()
|
||||
|
||||
|
||||
@message('LinkDestroy')
|
||||
def test_network_events_handle_message_LinkDestroy_bad_device_map1():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['LinkDestroy', dict(
|
||||
msg_type='LinkDestroy',
|
||||
id=1,
|
||||
sender=1,
|
||||
name="",
|
||||
from_device_id=1,
|
||||
to_device_id=2,
|
||||
from_interface_id=1,
|
||||
to_interface_id=1
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock,\
|
||||
mock.patch.object(Device.objects, 'filter') as device_filter_mock,\
|
||||
mock.patch.object(Link.objects, 'filter'),\
|
||||
mock.patch.object(Interface.objects, 'get') as interface_get_mock:
|
||||
values_mock = mock.MagicMock()
|
||||
interface_get_mock.return_value = mock.MagicMock()
|
||||
interface_get_mock.return_value.pk = 7
|
||||
device_filter_mock.return_value = values_mock
|
||||
values_mock.values_list.return_value = [(9,1), (2,2)]
|
||||
networking_events_dispatcher.handle(message)
|
||||
log_mock.assert_called_once_with('Device not found')
|
||||
|
||||
|
||||
@message('LinkDestroy')
|
||||
def test_network_events_handle_message_LinkDestroy_bad_device_map2():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['LinkDestroy', dict(
|
||||
msg_type='LinkDestroy',
|
||||
id=1,
|
||||
sender=1,
|
||||
name="",
|
||||
from_device_id=1,
|
||||
to_device_id=2,
|
||||
from_interface_id=1,
|
||||
to_interface_id=1
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock,\
|
||||
mock.patch.object(Device.objects, 'filter') as device_filter_mock,\
|
||||
mock.patch.object(Link.objects, 'filter'),\
|
||||
mock.patch.object(Interface.objects, 'get') as interface_get_mock:
|
||||
values_mock = mock.MagicMock()
|
||||
interface_get_mock.return_value = mock.MagicMock()
|
||||
interface_get_mock.return_value.pk = 7
|
||||
device_filter_mock.return_value = values_mock
|
||||
values_mock.values_list.return_value = [(1,1), (9,2)]
|
||||
networking_events_dispatcher.handle(message)
|
||||
log_mock.assert_called_once_with('Device not found')
|
||||
|
||||
|
||||
@message('LinkSelected')
|
||||
def test_network_events_handle_message_LinkSelected():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['LinkSelected', dict(
|
||||
msg_type='LinkSelected',
|
||||
sender=1,
|
||||
id=1
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock:
|
||||
networking_events_dispatcher.handle(message)
|
||||
log_mock.assert_not_called()
|
||||
|
||||
|
||||
@message('LinkUnSelected')
|
||||
def test_network_events_handle_message_LinkUnSelected():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['LinkUnSelected', dict(
|
||||
msg_type='LinkUnSelected',
|
||||
sender=1,
|
||||
id=1
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock:
|
||||
networking_events_dispatcher.handle(message)
|
||||
log_mock.assert_not_called()
|
||||
|
||||
|
||||
@message('MultipleMessage')
|
||||
def test_network_events_handle_message_MultipleMessage_unsupported_message():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['MultipleMessage', dict(
|
||||
msg_type='MultipleMessage',
|
||||
sender=1,
|
||||
messages=[dict(msg_type="Unsupported")]
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock:
|
||||
networking_events_dispatcher.handle(message)
|
||||
log_mock.assert_called_once_with(
|
||||
'Unsupported message %s', u'Unsupported')
|
||||
|
||||
|
||||
@message('MultipleMessage')
|
||||
def test_network_events_handle_message_MultipleMessage():
|
||||
logger = logging.getLogger('awx.network_ui.consumers')
|
||||
message_data = ['MultipleMessage', dict(
|
||||
msg_type='MultipleMessage',
|
||||
sender=1,
|
||||
messages=[dict(msg_type="DeviceSelected")]
|
||||
)]
|
||||
message = {'topology': 1, 'client': 1, 'text': json.dumps(message_data)}
|
||||
with mock.patch.object(logger, 'warning') as log_mock:
|
||||
networking_events_dispatcher.handle(message)
|
||||
log_mock.assert_not_called()
|
9
awx/network_ui/tests/unit/test_routing.py
Normal file
9
awx/network_ui/tests/unit/test_routing.py
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
import awx.network_ui.routing
|
||||
|
||||
|
||||
def test_routing():
|
||||
'''
|
||||
Tests that the number of routes in awx.network_ui.routing is 3.
|
||||
'''
|
||||
assert len(awx.network_ui.routing.channel_routing) == 3
|
65
awx/network_ui/tests/unit/test_views.py
Normal file
65
awx/network_ui/tests/unit/test_views.py
Normal file
@ -0,0 +1,65 @@
|
||||
|
||||
import mock
|
||||
|
||||
from awx.network_ui.views import topology_data, NetworkAnnotatedInterface, json_topology_data, yaml_topology_data
|
||||
from awx.network_ui.models import Topology, Device, Link, Interface
|
||||
|
||||
|
||||
|
||||
def test_topology_data():
|
||||
with mock.patch.object(Topology, 'objects'),\
|
||||
mock.patch.object(Device, 'objects') as device_objects_mock,\
|
||||
mock.patch.object(Link, 'objects') as link_objects_mock,\
|
||||
mock.patch.object(Interface, 'objects'),\
|
||||
mock.patch.object(NetworkAnnotatedInterface, 'filter'):
|
||||
device_objects_mock.filter.return_value.order_by.return_value = [
|
||||
Device(pk=1), Device(pk=2)]
|
||||
link_objects_mock.filter.return_value = [Link(from_device=Device(name='from', cid=1),
|
||||
to_device=Device(
|
||||
name='to', cid=2),
|
||||
from_interface=Interface(
|
||||
name="eth0", cid=1),
|
||||
to_interface=Interface(
|
||||
name="eth0", cid=1),
|
||||
name="",
|
||||
pk=1
|
||||
)]
|
||||
data = topology_data(1)
|
||||
assert len(data['devices']) == 2
|
||||
assert len(data['links']) == 1
|
||||
|
||||
|
||||
def test_json_topology_data():
|
||||
request = mock.MagicMock()
|
||||
request.GET = dict(topology_id=1)
|
||||
with mock.patch('awx.network_ui.views.topology_data') as topology_data_mock:
|
||||
topology_data_mock.return_value = dict()
|
||||
json_topology_data(request)
|
||||
topology_data_mock.assert_called_once_with(1)
|
||||
|
||||
|
||||
def test_yaml_topology_data():
|
||||
request = mock.MagicMock()
|
||||
request.GET = dict(topology_id=1)
|
||||
with mock.patch('awx.network_ui.views.topology_data') as topology_data_mock:
|
||||
topology_data_mock.return_value = dict()
|
||||
yaml_topology_data(request)
|
||||
topology_data_mock.assert_called_once_with(1)
|
||||
|
||||
|
||||
def test_json_topology_data_no_topology_id():
|
||||
request = mock.MagicMock()
|
||||
request.GET = dict()
|
||||
with mock.patch('awx.network_ui.views.topology_data') as topology_data_mock:
|
||||
topology_data_mock.return_value = dict()
|
||||
json_topology_data(request)
|
||||
topology_data_mock.assert_not_called()
|
||||
|
||||
|
||||
def test_yaml_topology_data_no_topology_id():
|
||||
request = mock.MagicMock()
|
||||
request.GET = dict()
|
||||
with mock.patch('awx.network_ui.views.topology_data') as topology_data_mock:
|
||||
topology_data_mock.return_value = dict()
|
||||
yaml_topology_data(request)
|
||||
topology_data_mock.assert_not_called()
|
@ -1,11 +1,9 @@
|
||||
# Copyright (c) 2017 Red Hat, Inc
|
||||
from django.shortcuts import render
|
||||
from django import forms
|
||||
from django.http import JsonResponse, HttpResponseBadRequest, HttpResponse
|
||||
from awx.network_ui.models import Topology, Device, Link, Interface
|
||||
from django.db.models import Q
|
||||
import yaml
|
||||
import json
|
||||
|
||||
NetworkAnnotatedInterface = Interface.objects.values('name',
|
||||
'cid',
|
||||
@ -63,18 +61,6 @@ def topology_data(topology_id):
|
||||
return data
|
||||
|
||||
|
||||
def yaml_serialize_topology(topology_id):
|
||||
return yaml.safe_dump(topology_data(topology_id), default_flow_style=False)
|
||||
|
||||
|
||||
def json_serialize_topology(topology_id):
|
||||
return json.dumps(topology_data(topology_id))
|
||||
|
||||
|
||||
def index(request):
|
||||
return render(request, "network_ui/index.html", dict(topologies=Topology.objects.all().order_by('-pk')))
|
||||
|
||||
|
||||
class TopologyForm(forms.Form):
|
||||
topology_id = forms.IntegerField()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user