From d600145da4833e14cee0bb2693e5be9ceaa6dd79 Mon Sep 17 00:00:00 2001 From: Benjamin Bertrand <benjamin.bertrand@esss.se> Date: Wed, 18 Dec 2019 13:03:51 +0100 Subject: [PATCH] Coerce stack_member to int in the form stack_member was incorrectly coerced to a string JIRA INFRA-1648 #action In Progress --- app/inventory/forms.py | 2 +- app/models.py | 4 ++-- app/utils.py | 10 ++++++++- tests/functional/test_web.py | 39 ++++++++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/app/inventory/forms.py b/app/inventory/forms.py index be25524..f3d7bde 100644 --- a/app/inventory/forms.py +++ b/app/inventory/forms.py @@ -51,7 +51,7 @@ class ItemForm(CSEntryForm): parent_id = SelectField("Parent", coerce=utils.coerce_to_str_or_none) host_id = SelectField("Host", coerce=utils.coerce_to_str_or_none) stack_member = NoValidateSelectField( - "Stack member", coerce=utils.coerce_to_str_or_none, choices=[] + "Stack member", coerce=utils.coerce_to_int_or_none, choices=[] ) mac_addresses = StringField( "MAC addresses", diff --git a/app/models.py b/app/models.py index dd0413e..2cd7965 100644 --- a/app/models.py +++ b/app/models.py @@ -689,7 +689,7 @@ class Item(CreatedMixin, SearchableMixin, db.Model): "children": {"type": "text", "fields": {"keyword": {"type": "keyword"}}}, "macs": {"type": "text", "fields": {"keyword": {"type": "keyword"}}}, "host": {"type": "text", "fields": {"keyword": {"type": "keyword"}}}, - "stack_member": {"type": "text", "fields": {"keyword": {"type": "keyword"}}}, + "stack_member": {"type": "byte"}, "history": {"enabled": False}, "comments": {"type": "text"}, } @@ -1293,7 +1293,7 @@ class Host(CreatedMixin, SearchableMixin, db.Model): # This function replaces None by Inf so it is set at the end of the list # items are sorted by stack_member and then ics_id def none_to_inf(nb): - return float("inf") if nb is None else nb + return float("inf") if nb is None else int(nb) d = super().to_dict() d.update( diff --git a/app/utils.py b/app/utils.py index b053226..cf52ea1 100644 --- a/app/utils.py +++ b/app/utils.py @@ -192,7 +192,7 @@ def lowercase_field(value): return value -# coerce function to use with SelectField that can accept a None value +# coerce functions to use with SelectField that can accept a None value # wtforms always coerce to string by default # Values returned from the form are usually strings but if a field is disabled # None is returned @@ -204,6 +204,14 @@ def coerce_to_str_or_none(value): return str(value) +def coerce_to_int_or_none(value): + """Return None if the value is not an integer""" + try: + return int(value) + except ValueError: + return None + + def parse_to_utc(string): """Convert a string to a datetime object with no timezone""" d = dateutil.parser.parse(string) diff --git a/tests/functional/test_web.py b/tests/functional/test_web.py index 8827f2d..8a7fd56 100644 --- a/tests/functional/test_web.py +++ b/tests/functional/test_web.py @@ -709,3 +709,42 @@ def test_create_item_invalid_ics_id(logged_rw_client): assert response.status_code == 200 assert b"Register new item" in response.data assert b"The ICS id shall be composed of 3 letters and 3 digits" in response.data + + +def test_create_item_with_stack_member( + host_factory, device_type_factory, item_factory, logged_rw_client +): + # Test for JIRA INFRA-1648 + network_type = device_type_factory(name="NETWORK") + host = host_factory(device_type=network_type) + item1 = item_factory(ics_id="AAA001", host=host, stack_member=0) + ics_id = "AAA042" + form = { + "ics_id": ics_id, + "serial_number": "12345", + "host_id": host.id, + "stack_member": 1, + } + response = logged_rw_client.post(f"/inventory/items/create", data=form) + assert response.status_code == 302 + item2 = models.Item.query.filter_by(ics_id=ics_id).first() + assert host.stack_members() == [item1, item2] + + +def test_create_item_with_host_and_no_stack_member( + host_factory, device_type_factory, item_factory, logged_rw_client +): + network_type = device_type_factory(name="NETWORK") + host = host_factory(device_type=network_type) + ics_id = "AAA042" + form = { + "ics_id": ics_id, + "serial_number": "12345", + "host_id": host.id, + "stack_member": "", + } + response = logged_rw_client.post(f"/inventory/items/create", data=form) + assert response.status_code == 302 + item = models.Item.query.filter_by(ics_id=ics_id).first() + assert item.host == host + assert item.stack_member is None -- GitLab