Skip to content

Commit

Permalink
fix: add groups and single hosts in separate fields. Clear notoficati…
Browse files Browse the repository at this point in the history
…on when some record wasn't edited or added (#38)

fix: fix broken test

fix: remove unused imports

fix: validate situation when user tries to add host which has the same name as a group configured in groups or reverse situation

fix: allow adding host names staring with a digit

fix: update get_inventory_type function and tests
  • Loading branch information
wojtekzyla authored Aug 2, 2023
1 parent 7e4e8ef commit 86b4cff
Show file tree
Hide file tree
Showing 25 changed files with 608 additions and 203 deletions.
3 changes: 3 additions & 0 deletions backend/SC4SNMP_UI_backend/common/backend_ui_conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,13 +277,16 @@ def ui2backend(self, document: dict, **kwargs):
raise ValueError("No delete provided")

def backend2ui(self, document: dict, **kwargs):
if "inventory_type" not in kwargs.keys():
raise ValueError("No inventory_type provided")
profiles_mongo = document['profiles']
if len(profiles_mongo) > 0:
profiles = profiles_mongo.split(";")
else:
profiles = []
result = {
'_id': str(document["_id"]),
'inventoryType': kwargs['inventory_type'],
'address': document['address'],
'port': str(document['port']),
'version': document['version'],
Expand Down
33 changes: 22 additions & 11 deletions backend/SC4SNMP_UI_backend/common/inventory_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ class HostConfiguration(Enum):
SINGLE = 1
GROUP = 2

def get_inventory_type(document):
if list(mongo_groups.find({document["address"]: {"$exists": 1}})):
result = "Group"
else:
result = "Host"
return result

def update_profiles_in_inventory(profile_to_search: str, process_record: Callable, **kwargs):
"""
When profile is edited, then in some cases inventory records using this profile should be updated.
Expand All @@ -25,7 +32,7 @@ def update_profiles_in_inventory(profile_to_search: str, process_record: Callabl
inventory_records = list(mongo_inventory.find({"profiles": {"$regex": f'.*{profile_to_search}.*'}}))
for record in inventory_records:
record_id = record["_id"]
record_updated = inventory_conversion.backend2ui(record)
record_updated = inventory_conversion.backend2ui(record, inventory_type=None) # inventory_type isn't used
index_to_update = record_updated["profiles"].index(profile_to_search)
record_updated = process_record(index_to_update, record_updated, kwargs)
record_updated = inventory_conversion.ui2backend(record_updated, delete=False)
Expand Down Expand Up @@ -92,11 +99,15 @@ def _is_host_configured(self, address: str, port: str):
def add_single_host(self, address, port, device_object=None, add: bool=True):
host_configured, deleted_inventory_record, host_configuration, existing_id_string, group_name = \
self._is_host_configured(address, port)
groups = list(mongo_groups.find({address: {"$exists": True}}))
if host_configured:
host_location_message = "as a single host in the inventory" if host_configuration == HostConfiguration.SINGLE else \
host_location_message = "in the inventory" if host_configuration == HostConfiguration.SINGLE else \
f"in group {group_name}"
message = f"Host {address}:{port} already exists {host_location_message}. Record was not added."
host_added = False
elif groups:
message = f"There is a group with the same name configured. Record {address} can't be added as a single host."
host_added = False
else:
if add and device_object is not None:
self._mongo_inventory.insert_one(device_object)
Expand Down Expand Up @@ -130,7 +141,7 @@ def edit_single_host(self, address: str, port: str, host_id: str, device_object=
if len(deleted_inventory_record) > 0:
self._mongo_inventory.delete_one({"_id": deleted_inventory_record[0]["_id"]})
else:
host_location_message = "as a single host in the inventory" if host_configuration == HostConfiguration.SINGLE else \
host_location_message = "in the inventory" if host_configuration == HostConfiguration.SINGLE else \
f"in group {group_name}"
message = f"Host {address}:{port} already exists {host_location_message}. Record was not edited."
host_edited = False
Expand Down Expand Up @@ -191,12 +202,9 @@ def add_group_to_inventory(self, group_name: str, group_port: str, group_object=
existing_inventory_record = list(self._mongo_inventory.find({'address': group_name, "delete": False}))
deleted_inventory_record = list(self._mongo_inventory.find({'address': group_name, "delete": True}))
group = list(self._mongo_groups.find({group_name: {"$exists": 1}}))
if len(group) == 0 and len(existing_inventory_record) == 0:
group_added = True
message = f"Group {group_name} doesn't exist in the configuration. Treating {group_name} as a hostname."
elif len(group) == 0 and len(existing_inventory_record) > 0:
if len(group) == 0:
group_added = False
message = f"{group_name} has already been configured. Record was not added."
message = f"Group {group_name} doesn't exist in the configuration. Record was not added."
elif len(existing_inventory_record) > 0:
group_added = False
message = f"Group {group_name} has already been added to the inventory. Record was not added."
Expand Down Expand Up @@ -229,8 +237,11 @@ def edit_group_in_inventory(self, group_name: str, group_id: str, group_object=N
group_id = ObjectId(group_id)
existing_inventory_record = list(self._mongo_inventory.find({'address': group_name, "delete": False}))
deleted_inventory_record = list(self._mongo_inventory.find({'address': group_name, "delete": True}))

if len(existing_inventory_record) == 0 or (len(existing_inventory_record) > 0 and existing_inventory_record[0]["_id"] == group_id):
group = list(self._mongo_groups.find({group_name: {"$exists": 1}}))
if len(group) == 0:
group_edited = False
message = f"Group {group_name} doesn't exist in the configuration. Record was not edited."
elif len(existing_inventory_record) == 0 or (len(existing_inventory_record) > 0 and existing_inventory_record[0]["_id"] == group_id):
message = "success"
group_edited = True
if edit and group_object is not None:
Expand All @@ -249,7 +260,7 @@ def edit_group_in_inventory(self, group_name: str, group_id: str, group_object=N
if len(deleted_inventory_record) > 0:
self._mongo_inventory.delete_one({"_id": deleted_inventory_record[0]["_id"]})
else:
message = f"Group wit name {group_name} already exists. Record was not edited."
message = f"Group with name {group_name} already exists. Record was not edited."
group_edited = False

return group_edited, message
13 changes: 11 additions & 2 deletions backend/SC4SNMP_UI_backend/groups/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from SC4SNMP_UI_backend.common.backend_ui_conversions import GroupConversion, GroupDeviceConversion, InventoryConversion, \
get_group_or_profile_name_from_backend
from copy import copy
from SC4SNMP_UI_backend.common.inventory_utils import HandleNewDevice
from SC4SNMP_UI_backend.common.inventory_utils import HandleNewDevice, get_inventory_type

groups_blueprint = Blueprint('groups_blueprint', __name__)

Expand Down Expand Up @@ -35,6 +35,10 @@ def add_group_record():
if len(same_name_groups) > 0:
result = jsonify(
{"message": f"Group with name {group_obj['groupName']} already exists. Group was not added."}), 400
elif list(mongo_inventory.find({"address": group_obj['groupName'], "delete": False})):
result = jsonify(
{"message": f"In the inventory there is a record with name {group_obj['groupName']}. Group was not added."}
), 400
else:
group_obj = group_conversion.ui2backend(group_obj)
mongo_groups.insert_one(group_obj)
Expand All @@ -50,6 +54,10 @@ def update_group(group_id):
if len(same_name_groups) > 0:
result = jsonify(
{"message": f"Group with name {group_obj['groupName']} already exists. Group was not edited."}), 400
elif list(mongo_inventory.find({"address": group_obj['groupName'], "delete": False})):
result = jsonify(
{"message": f"In the inventory there is a record with name {group_obj['groupName']}. Group was not edited."}
), 400
else:
old_group = list(mongo_groups.find({'_id': ObjectId(group_id)}))[0]
old_group_name = get_group_or_profile_name_from_backend(old_group)
Expand Down Expand Up @@ -110,7 +118,8 @@ def get_devices_of_group(group_id, page_num, dev_per_page):
def get_group_config_from_inventory(group_name):
group_from_inventory = list(mongo_inventory.find({"address": group_name, "delete": False}))
if len(group_from_inventory) > 0:
result = jsonify(inventory_conversion.backend2ui(group_from_inventory[0])), 200
inventory_type = get_inventory_type(group_from_inventory[0])
result = jsonify(inventory_conversion.backend2ui(group_from_inventory[0], inventory_type=inventory_type)), 200
else:
result = "", 204
return result
Expand Down
18 changes: 9 additions & 9 deletions backend/SC4SNMP_UI_backend/inventory/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
from flask_cors import cross_origin
from SC4SNMP_UI_backend import mongo_client
from SC4SNMP_UI_backend.common.backend_ui_conversions import InventoryConversion
from SC4SNMP_UI_backend.common.inventory_utils import HandleNewDevice
from SC4SNMP_UI_backend.common.inventory_utils import HandleNewDevice, get_inventory_type

inventory_blueprint = Blueprint('inventory_blueprint', __name__)

inventory_conversion = InventoryConversion()
mongo_groups = mongo_client.sc4snmp.groups_ui
mongo_inventory = mongo_client.sc4snmp.inventory_ui


@inventory_blueprint.route('/inventory/<page_num>/<dev_per_page>')
@cross_origin()
def get_inventory_list(page_num, dev_per_page):
Expand All @@ -22,7 +21,8 @@ def get_inventory_list(page_num, dev_per_page):
inventory = list(mongo_inventory.find({"delete": False}).skip(skips).limit(dev_per_page))
inventory_list = []
for inv in inventory:
inventory_list.append(inventory_conversion.backend2ui(inv))
inventory_type = get_inventory_type(inv)
inventory_list.append(inventory_conversion.backend2ui(inv, inventory_type=inventory_type))
return jsonify(inventory_list)


Expand All @@ -37,9 +37,10 @@ def get_inventory_count():
@cross_origin()
def add_inventory_record():
inventory_obj = request.json
inventory_type = inventory_obj["inventoryType"]
inventory_obj = inventory_conversion.ui2backend(inventory_obj, delete=False)
handler = HandleNewDevice(mongo_groups, mongo_inventory)
if inventory_obj["address"][0].isdigit():
if inventory_type == "Host":
record_added, message = handler.add_single_host(inventory_obj["address"], str(inventory_obj["port"]),
inventory_obj, True)
else:
Expand Down Expand Up @@ -68,23 +69,22 @@ def delete_inventory_record(inventory_id):
@cross_origin()
def update_inventory_record(inventory_id):
inventory_obj = request.json
inventory_type = inventory_obj["inventoryType"]
inventory_obj = inventory_conversion.ui2backend(inventory_obj, delete=False)
current_inventory = list(mongo_inventory.find({"_id": ObjectId(inventory_id)}))[0]
current_inventory_type = get_inventory_type(current_inventory)
handler = HandleNewDevice(mongo_groups, mongo_inventory)

is_current_a_single_host = current_inventory["address"][0].isdigit()
is_new_a_single_host = inventory_obj["address"][0].isdigit()
if is_current_a_single_host != is_new_a_single_host:
if inventory_type != current_inventory_type:
result = jsonify({"message": "Can't edit single host to the group or group to the single host"}), 400
else:
if is_new_a_single_host:
if inventory_type == "Host":
record_edited, message = handler.edit_single_host(inventory_obj["address"], str(inventory_obj["port"]),
str(inventory_id), inventory_obj, True)
else:
record_edited, message = handler.edit_group_in_inventory(inventory_obj["address"], str(inventory_id), inventory_obj, True)
if record_edited:
if message == "success" or message is None:
print(message)
result = jsonify("success"), 200
else:
result = jsonify({"message": message}), 200
Expand Down
6 changes: 4 additions & 2 deletions backend/tests/common/test_backend_ui_conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ def setUpClass(cls):

cls.ui_inventory_1 = {
"_id": common_id,
"inventoryType": "Host",
"address": "11.0.78.114",
"port": "161",
"version": "3",
Expand Down Expand Up @@ -234,6 +235,7 @@ def setUpClass(cls):

cls.ui_inventory_2 = {
"_id": common_id,
"inventoryType": "Group",
"address": "group_1",
"port": "1161",
"version": "2c",
Expand Down Expand Up @@ -320,8 +322,8 @@ def test_group_device_ui_to_backend(self):
self.assertDictEqual(group_device_conversion.ui2backend(self.ui_group_device_4), device)

def test_inventory_backend_to_ui(self):
self.assertDictEqual(inventory_conversion.backend2ui(self.backend_inventory_1), self.ui_inventory_1)
self.assertDictEqual(inventory_conversion.backend2ui(self.backend_inventory_2), self.ui_inventory_2)
self.assertDictEqual(inventory_conversion.backend2ui(self.backend_inventory_1, inventory_type="Host"), self.ui_inventory_1)
self.assertDictEqual(inventory_conversion.backend2ui(self.backend_inventory_2, inventory_type="Group"), self.ui_inventory_2)

def test_inventory_ui_to_backend(self):
back_inv = self.backend_inventory_1
Expand Down
9 changes: 7 additions & 2 deletions backend/tests/ui_handling/get_endpoints/test_get_endpoints.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from unittest import mock
from bson import ObjectId


@mock.patch("pymongo.collection.Collection.find")
def test_get_profile_names(m_client, client):
m_client.return_value = [{
Expand Down Expand Up @@ -264,8 +263,9 @@ def test_get_devices_of_group(m_client, client):
assert response.json == third_result


@mock.patch("SC4SNMP_UI_backend.inventory.routes.get_inventory_type")
@mock.patch("pymongo.cursor.Cursor.limit")
def test_get_inventory_list(m_cursor, client):
def test_get_inventory_list(m_cursor, m_get_inventory_type, client):
common_id = "635916b2c8cb7a15f28af40a"

m_cursor.side_effect = [
Expand Down Expand Up @@ -314,9 +314,12 @@ def test_get_inventory_list(m_cursor, client):
]
]

m_get_inventory_type.side_effect = ["Host", "Group", "Group"]

first_result = [
{
"_id": common_id,
"inventoryType": "Host",
"address": "11.0.78.114",
"port": "161",
"version": "3",
Expand All @@ -329,6 +332,7 @@ def test_get_inventory_list(m_cursor, client):
},
{
"_id": common_id,
"inventoryType": "Group",
"address": "group_1",
"port": "1161",
"version": "2c",
Expand All @@ -344,6 +348,7 @@ def test_get_inventory_list(m_cursor, client):
second_result = [
{
"_id": common_id,
"inventoryType": "Group",
"address": "group_2",
"port": "161",
"version": "3",
Expand Down
Loading

0 comments on commit 86b4cff

Please sign in to comment.