From b6b8f43badcf94f107660a2e3e704aae9425745f Mon Sep 17 00:00:00 2001 From: Benjamin Bertrand <benjamin.bertrand@esss.se> Date: Fri, 27 Jul 2018 19:12:18 +0200 Subject: [PATCH] Add Ansible groups parent - child --- app/models.py | 29 +++++++++++++ ...78283a288a05_add_ansible_group_children.py | 43 +++++++++++++++++++ tests/functional/test_api.py | 13 ++++-- tests/functional/test_models.py | 13 ++++++ 4 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 migrations/versions/78283a288a05_add_ansible_group_children.py diff --git a/app/models.py b/app/models.py index d3745fe..c234a4b 100644 --- a/app/models.py +++ b/app/models.py @@ -744,6 +744,24 @@ class DeviceType(db.Model): } +# Table required for Many-to-Many relationships between Ansible parent and child groups +ansible_groups_parent_child_table = db.Table( + "ansible_groups_parent_child", + db.Column( + "parent_group_id", + db.Integer, + db.ForeignKey("ansible_group.id"), + primary_key=True, + ), + db.Column( + "child_group_id", + db.Integer, + db.ForeignKey("ansible_group.id"), + primary_key=True, + ), +) + + # Table required for Many-to-Many relationships between Ansible groups and hosts ansible_groups_hosts_table = db.Table( "ansible_groups_hosts", @@ -759,9 +777,19 @@ ansible_groups_hosts_table = db.Table( class AnsibleGroup(CreatedMixin, db.Model): __tablename__ = "ansible_group" + # Define id here so that it can be used in the primary and secondary join + id = db.Column(db.Integer, primary_key=True) name = db.Column(CIText, nullable=False, unique=True) vars = db.Column(postgresql.JSONB) + children = db.relationship( + "AnsibleGroup", + secondary=ansible_groups_parent_child_table, + primaryjoin=id == ansible_groups_parent_child_table.c.parent_group_id, + secondaryjoin=id == ansible_groups_parent_child_table.c.child_group_id, + backref=db.backref("parents"), + ) + def __str__(self): return str(self.name) @@ -772,6 +800,7 @@ class AnsibleGroup(CreatedMixin, db.Model): "name": self.name, "vars": self.vars, "hosts": [str(host) for host in self.hosts], + "children": [str(child) for child in self.children], } ) return d diff --git a/migrations/versions/78283a288a05_add_ansible_group_children.py b/migrations/versions/78283a288a05_add_ansible_group_children.py new file mode 100644 index 0000000..d83e8d5 --- /dev/null +++ b/migrations/versions/78283a288a05_add_ansible_group_children.py @@ -0,0 +1,43 @@ +"""Add Ansible group children + +Revision ID: 78283a288a05 +Revises: 924d15deb321 +Create Date: 2018-07-27 17:05:57.105899 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "78283a288a05" +down_revision = "924d15deb321" +branch_labels = None +depends_on = None + + +def upgrade(): + op.create_table( + "ansible_groups_parent_child", + sa.Column("parent_group_id", sa.Integer(), nullable=False), + sa.Column("child_group_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint( + ["child_group_id"], + ["ansible_group.id"], + name=op.f("fk_ansible_groups_parent_child_child_group_id_ansible_group"), + ), + sa.ForeignKeyConstraint( + ["parent_group_id"], + ["ansible_group.id"], + name=op.f("fk_ansible_groups_parent_child_parent_group_id_ansible_group"), + ), + sa.PrimaryKeyConstraint( + "parent_group_id", + "child_group_id", + name=op.f("pk_ansible_groups_parent_child"), + ), + ) + + +def downgrade(): + op.drop_table("ansible_groups_parent_child") diff --git a/tests/functional/test_api.py b/tests/functional/test_api.py index 9efc9fc..677fc35 100644 --- a/tests/functional/test_api.py +++ b/tests/functional/test_api.py @@ -1159,9 +1159,16 @@ def test_create_ansible_group(client, admin_token): data = {"name": "mygroup"} response = post(client, f"{API_URL}/network/groups", data=data, token=admin_token) assert response.status_code == 201 - assert {"id", "name", "vars", "hosts", "created_at", "updated_at", "user"} == set( - response.json.keys() - ) + assert { + "id", + "name", + "vars", + "hosts", + "children", + "created_at", + "updated_at", + "user", + } == set(response.json.keys()) assert response.json["name"] == data["name"] # Check that name shall be unique diff --git a/tests/functional/test_models.py b/tests/functional/test_models.py index 2c6233b..2a40e1f 100644 --- a/tests/functional/test_models.py +++ b/tests/functional/test_models.py @@ -179,6 +179,19 @@ def test_ansible_groups(ansible_group_factory, host_factory): assert group2.hosts == [host1] +def test_ansible_groups_children(ansible_group_factory, host_factory): + group1 = ansible_group_factory() + group2 = ansible_group_factory() + group3 = ansible_group_factory() + group1.children.append(group2) + group1.children.append(group3) + assert group1.children == [group2, group3] + assert group2.parents == [group1] + assert group3.parents == [group1] + group4 = ansible_group_factory(parents=[group1]) + assert group1.children == [group2, group3, group4] + + def test_host_model(model_factory, item_factory, host_factory): host1 = host_factory() model1 = model_factory(name="EX3400") -- GitLab