From 0c5c388e6e26c3b6b3cad78d91df52e7f05abb05 Mon Sep 17 00:00:00 2001
From: Benjamin Bertrand <benjamin.bertrand@esss.se>
Date: Wed, 20 Dec 2017 08:19:08 +0100
Subject: [PATCH] Update cnames / interface relationship

Add delete and delete-orphan options to the cascade behavior:
- delete: delete from database associated cnames when deleting an
  interface
- delete-orphan: delete cname when removing it from the list of
  interface.cnames
---
 app/models.py        | 6 +++++-
 app/network/views.py | 9 +++++++--
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/app/models.py b/app/models.py
index 4eb7af5..2de41f1 100644
--- a/app/models.py
+++ b/app/models.py
@@ -487,7 +487,11 @@ class Interface(db.Model):
     mac_id = db.Column(db.Integer, db.ForeignKey('mac.id'))
     host_id = db.Column(db.Integer, db.ForeignKey('host.id'))
 
-    cnames = db.relationship('Cname', backref='interface')
+    # Add delete and delete-orphan options to automatically delete cnames when:
+    # - deleting an interface
+    # - de-associating a cname (removing it from the interface.cnames list)
+    cnames = db.relationship('Cname', backref='interface',
+                             cascade='all, delete, delete-orphan')
     tags = db.relationship('Tag', secondary=interfacetags_table, lazy='subquery',
                            backref=db.backref('interfaces', lazy=True))
 
diff --git a/app/network/views.py b/app/network/views.py
index 0caaa91..a14be57 100644
--- a/app/network/views.py
+++ b/app/network/views.py
@@ -160,8 +160,10 @@ def edit_interface(name):
         for (index, cname) in enumerate(interface.cnames):
             if cname.name not in new_cnames_string:
                 current_app.logger.debug(f'Deleting cname: {cname}')
-                interface.cnames.pop(index)
-                db.session.delete(cname)
+                # Removing the cname from interface.cnames list will
+                # delete it from the database due to the cascade
+                # delete-orphan option defined on the model
+                del interface.cnames[index]
         # Add new cnames
         for name in new_cnames_string:
             if name not in cnames_string:
@@ -189,6 +191,9 @@ def edit_interface(name):
 def delete_interface():
     interface = models.Interface.query.get_or_404(request.form['interface_id'])
     hostname = interface.host.name
+    # Deleting the interface will also delete all
+    # associated cnames due to the cascade delete option
+    # defined on the model
     db.session.delete(interface)
     db.session.commit()
     flash(f'Interface {interface.name} has been deleted', 'success')
-- 
GitLab