From 2aa97a52840c64d0bba01bf95de0b74ad8e98348 Mon Sep 17 00:00:00 2001 From: Benjamin Bertrand <benjamin.bertrand@esss.se> Date: Sun, 3 Feb 2019 17:13:56 +0100 Subject: [PATCH] Make sure the first interface is the main one Host interfaces are always returned sorted by name JIRA INFRA-785 #action In Progress --- app/models.py | 13 +++++++------ app/network/views.py | 8 ++++++++ tests/functional/test_api.py | 4 ++-- tests/functional/test_models.py | 16 ++++++++++------ 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/app/models.py b/app/models.py index 0214a12..41a0ed6 100644 --- a/app/models.py +++ b/app/models.py @@ -1134,13 +1134,18 @@ class Host(CreatedMixin, SearchableMixin, db.Model): ) ansible_vars = db.Column(postgresql.JSONB) - # Set cascade to all (to add delete) and delete-orphan to delete all interfaces + # 1. Set cascade to all (to add delete) and delete-orphan to delete all interfaces # when deleting a host + # 2. Return interfaces sorted by name so that the main one (the one starting with + # the same name as the host) is always the first one. + # As an interface name always has to start with the name of the host, the one + # matching the host name will always come first. interfaces = db.relationship( "Interface", backref=db.backref("host", lazy="joined"), cascade="all, delete-orphan", lazy="joined", + order_by="Interface.name", ) items = db.relationship( "Item", backref=db.backref("host", lazy="joined"), lazy="joined" @@ -1194,11 +1199,7 @@ class Host(CreatedMixin, SearchableMixin, db.Model): The main interface is the one that has the same name as the host or the first one found """ - for interface in self.interfaces: - if interface.name == self.name: - return interface - # No interface with the same name found... - # Return the first one + # As interfaces are sorted, the first one is always the main one try: return self.interfaces[0] except IndexError: diff --git a/app/network/views.py b/app/network/views.py index 756d35c..f69ff43 100644 --- a/app/network/views.py +++ b/app/network/views.py @@ -143,6 +143,14 @@ def delete_host(): @login_required def view_host(name): host = models.Host.query.filter_by(name=name).first_or_404() + if host.main_interface is None: + flash(f"Host {host.name} has no interface! Add one or delete it.", "warning") + elif host.main_interface.name != host.name: + flash( + f"The main interface '{host.main_interface.name}' shall have the same name as the host!" + f" Please rename it '{host.name}'.", + "warning", + ) if host.device_type.name == "Network": form = GenerateZTPConfigForm() elif host.device_type.name.startswith("Virtual"): diff --git a/tests/functional/test_api.py b/tests/functional/test_api.py index acecb7f..1c29607 100644 --- a/tests/functional/test_api.py +++ b/tests/functional/test_api.py @@ -1357,8 +1357,8 @@ def test_get_hosts_recursive(client, host_factory, interface_factory, readonly_t assert response.status_code == 200 assert len(response.get_json()) == 2 rhost1, rhost2 = response.get_json() - # We can't be sure in which order the interfaces are returned - assert set(rhost1["interfaces"]) == {interface11.name, interface12.name} + # Interfaces shall be sorted + assert rhost1["interfaces"] == sorted([interface11.name, interface12.name]) assert rhost2["interfaces"] == [interface21.name] # With recursive, interfaces are expanded response = get( diff --git a/tests/functional/test_models.py b/tests/functional/test_models.py index 4c25661..a35d263 100644 --- a/tests/functional/test_models.py +++ b/tests/functional/test_models.py @@ -441,25 +441,29 @@ def test_interface_name_existing_cname( def test_interface_is_main(host_factory, interface_factory): # The interface with the same name as the host is the main one host1 = host_factory(name="myhost") - interface11 = interface_factory(name=host1.name, host=host1) - interface12 = interface_factory(name=host1.name + "-2", host=host1) + interface11 = interface_factory(name=host1.name + "-2", host=host1) + interface12 = interface_factory(name=host1.name, host=host1) interface13 = interface_factory(name=host1.name + "-3", host=host1) - assert interface11.is_main - assert not interface12.is_main + assert interface12.is_main + assert not interface11.is_main assert not interface13.is_main + # Interfaces are sorted by name + assert host1.interfaces == [interface12, interface11, interface13] host2 = host_factory(name="anotherhost") interface21 = interface_factory(name=host2.name + "-1", host=host2) # If no interface has the same name as the host, the first one is the main assert interface21.is_main interface22 = interface_factory(name=host2.name + "-2", host=host2) # The first interface in the list is the main one - assert host2.interfaces[0].is_main - assert not host2.interfaces[1].is_main + assert host2.interfaces == [interface21, interface22] + assert interface21.is_main + assert not interface22.is_main interface23 = interface_factory(name=host2.name, host=host2) # The new interface has the same name as the host, so this is the main one assert not interface21.is_main assert not interface22.is_main assert interface23.is_main + assert host2.interfaces == [interface23, interface21, interface22] def test_host_existing_interface(db, host_factory, interface): -- GitLab