From c799ec6fb950190aa2245861ee43827821388ac1 Mon Sep 17 00:00:00 2001 From: Eric Fetty Date: Wed, 15 Jan 2025 13:39:47 -0600 Subject: [PATCH 1/9] =?UTF-8?q?fix:=20=F0=9F=90=9B=20refactor=20tag=20crea?= =?UTF-8?q?tion=20logic=20in=20ACI=20integration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nautobot_ssot/integrations/aci/signals.py | 35 ++++++++++------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/nautobot_ssot/integrations/aci/signals.py b/nautobot_ssot/integrations/aci/signals.py index 7cbc4602..030d510f 100644 --- a/nautobot_ssot/integrations/aci/signals.py +++ b/nautobot_ssot/integrations/aci/signals.py @@ -4,6 +4,7 @@ import logging import random +from django.contrib.contenttypes.models import ContentType from nautobot.core.signals import nautobot_database_ready from nautobot.extras.choices import CustomFieldTypeChoices @@ -20,36 +21,30 @@ def register_signals(sender): nautobot_database_ready.connect(device_custom_fields, sender=sender) nautobot_database_ready.connect(interface_custom_fields, sender=sender) +def _ensure_tag(apps, name, color): + """Ensure tag exists and properly configured.""" + tag = apps.get_model("extras", "Tag") + _tag = tag.objects.get_or_create(name=name)[0] + _tag.color == color + for content_type in ContentType.objects.all(): + if content_type not in _tag.content_types.all(): + _tag.content_types.add(content_type) + _tag.validated_save() def aci_create_tag(apps, **kwargs): """Add a tag.""" tag = apps.get_model("extras", "Tag") logger.info("Creating tags for ACI, interface status and Sites") + _ensure_tag(apps=apps, name=PLUGIN_CFG.get("tag"), color=PLUGIN_CFG.get("tag_color")) + _ensure_tag(apps=apps, name=PLUGIN_CFG.get("tag_up"), color=PLUGIN_CFG.get("tag_up_color")) + _ensure_tag(apps=apps, name=PLUGIN_CFG.get("tag_down"), color=PLUGIN_CFG.get("tag_down_color")) + _ensure_tag(apps=apps, name="ACI_MULTISITE", color="03a9f4") - tag.objects.update_or_create( - name=PLUGIN_CFG.get("tag"), - color=PLUGIN_CFG.get("tag_color"), - ) - tag.objects.update_or_create( - name=PLUGIN_CFG.get("tag_up"), - color=PLUGIN_CFG.get("tag_up_color"), - ) - tag.objects.update_or_create( - name=PLUGIN_CFG.get("tag_down"), - color=PLUGIN_CFG.get("tag_down_color"), - ) - tag.objects.update_or_create( - name="ACI_MULTISITE", - color="03a9f4", - ) apics = PLUGIN_CFG.get("apics") if apics: for key in apics: if ("SITE" in key or "STAGE" in key) and not tag.objects.filter(name=apics[key]).exists(): - tag.objects.update_or_create( - name=apics[key], - color="".join([random.choice("ABCDEF0123456789") for i in range(6)]), # noqa: S311 - ) + _ensure_tag(apps=apps, name=apics[key], color="".join([random.choice("ABCDEF0123456789") for i in range(6)])) # noqa: S311 def aci_create_manufacturer(apps, **kwargs): From a7be599f3fcf267c4746dfddfbad56bb1e505049 Mon Sep 17 00:00:00 2001 From: Eric Fetty Date: Wed, 15 Jan 2025 13:46:52 -0600 Subject: [PATCH 2/9] =?UTF-8?q?fix:=20=F0=9F=90=9B=20resolve=20ACI=20signa?= =?UTF-8?q?l=20tag=20initialization=20issues=20and=20prevent=20duplicate?= =?UTF-8?q?=20key=20exceptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changes/654.fixed | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changes/654.fixed diff --git a/changes/654.fixed b/changes/654.fixed new file mode 100644 index 00000000..894647d9 --- /dev/null +++ b/changes/654.fixed @@ -0,0 +1,2 @@ +Fixed ACI signal initializing Tags without ContentType or Color being populated +Fixed ACI signal initializing Tag throwing duplicate key exception. \ No newline at end of file From 4d8e14ed138ef4ace3ece111a9f88f5f9304ffd3 Mon Sep 17 00:00:00 2001 From: Eric Fetty Date: Wed, 15 Jan 2025 13:54:09 -0600 Subject: [PATCH 3/9] formatted with Ruff --- nautobot_ssot/integrations/aci/signals.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/aci/signals.py b/nautobot_ssot/integrations/aci/signals.py index 030d510f..d86cb50f 100644 --- a/nautobot_ssot/integrations/aci/signals.py +++ b/nautobot_ssot/integrations/aci/signals.py @@ -21,6 +21,7 @@ def register_signals(sender): nautobot_database_ready.connect(device_custom_fields, sender=sender) nautobot_database_ready.connect(interface_custom_fields, sender=sender) + def _ensure_tag(apps, name, color): """Ensure tag exists and properly configured.""" tag = apps.get_model("extras", "Tag") @@ -31,6 +32,7 @@ def _ensure_tag(apps, name, color): _tag.content_types.add(content_type) _tag.validated_save() + def aci_create_tag(apps, **kwargs): """Add a tag.""" tag = apps.get_model("extras", "Tag") @@ -44,7 +46,9 @@ def aci_create_tag(apps, **kwargs): if apics: for key in apics: if ("SITE" in key or "STAGE" in key) and not tag.objects.filter(name=apics[key]).exists(): - _ensure_tag(apps=apps, name=apics[key], color="".join([random.choice("ABCDEF0123456789") for i in range(6)])) # noqa: S311 + _ensure_tag( + apps=apps, name=apics[key], color="".join([random.choice("ABCDEF0123456789") for i in range(6)]) + ) # noqa: S311 def aci_create_manufacturer(apps, **kwargs): From 7a029545465b3d848275c6560f3c168e54925581 Mon Sep 17 00:00:00 2001 From: Eric Fetty Date: Wed, 15 Jan 2025 15:16:23 -0600 Subject: [PATCH 4/9] Move Ruff ignore commment to different line. --- nautobot_ssot/integrations/aci/signals.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nautobot_ssot/integrations/aci/signals.py b/nautobot_ssot/integrations/aci/signals.py index d86cb50f..0a0ca87b 100644 --- a/nautobot_ssot/integrations/aci/signals.py +++ b/nautobot_ssot/integrations/aci/signals.py @@ -47,8 +47,8 @@ def aci_create_tag(apps, **kwargs): for key in apics: if ("SITE" in key or "STAGE" in key) and not tag.objects.filter(name=apics[key]).exists(): _ensure_tag( - apps=apps, name=apics[key], color="".join([random.choice("ABCDEF0123456789") for i in range(6)]) - ) # noqa: S311 + apps=apps, name=apics[key], color="".join([random.choice("ABCDEF0123456789") for i in range(6)]) # noqa: S311 + ) def aci_create_manufacturer(apps, **kwargs): From eaf0bd03b818fa303c5b829efbe7823f01dacac2 Mon Sep 17 00:00:00 2001 From: Eric Fetty Date: Wed, 15 Jan 2025 15:19:13 -0600 Subject: [PATCH 5/9] reformat with Ruff --- nautobot_ssot/integrations/aci/signals.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/aci/signals.py b/nautobot_ssot/integrations/aci/signals.py index 0a0ca87b..82836fc3 100644 --- a/nautobot_ssot/integrations/aci/signals.py +++ b/nautobot_ssot/integrations/aci/signals.py @@ -47,7 +47,9 @@ def aci_create_tag(apps, **kwargs): for key in apics: if ("SITE" in key or "STAGE" in key) and not tag.objects.filter(name=apics[key]).exists(): _ensure_tag( - apps=apps, name=apics[key], color="".join([random.choice("ABCDEF0123456789") for i in range(6)]) # noqa: S311 + apps=apps, + name=apics[key], + color="".join([random.choice("ABCDEF0123456789") for i in range(6)]), # noqa: S311 ) From 63854eff6a28a5af3c74e3b92f839e177fecadcd Mon Sep 17 00:00:00 2001 From: Eric Fetty Date: Wed, 15 Jan 2025 15:39:49 -0600 Subject: [PATCH 6/9] =?UTF-8?q?fix:=20=F0=9F=90=9B=20ensure=20ContentType?= =?UTF-8?q?=20model=20is=20properly=20imported=20in=20tag=20creation=20log?= =?UTF-8?q?ic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nautobot_ssot/integrations/aci/signals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/aci/signals.py b/nautobot_ssot/integrations/aci/signals.py index 82836fc3..57ea0c61 100644 --- a/nautobot_ssot/integrations/aci/signals.py +++ b/nautobot_ssot/integrations/aci/signals.py @@ -4,7 +4,6 @@ import logging import random -from django.contrib.contenttypes.models import ContentType from nautobot.core.signals import nautobot_database_ready from nautobot.extras.choices import CustomFieldTypeChoices @@ -24,6 +23,7 @@ def register_signals(sender): def _ensure_tag(apps, name, color): """Ensure tag exists and properly configured.""" + ContentType = apps.get_model("contenttypes", "ContentType") tag = apps.get_model("extras", "Tag") _tag = tag.objects.get_or_create(name=name)[0] _tag.color == color From 1a219b537edd7ed31fe2aa9312d69b6e73cae2ca Mon Sep 17 00:00:00 2001 From: Eric Fetty Date: Wed, 15 Jan 2025 15:53:24 -0600 Subject: [PATCH 7/9] =?UTF-8?q?fix:=20=F0=9F=90=9B=20update=20tag=20color?= =?UTF-8?q?=20only=20if=20it=20differs=20and=20ensure=20proper=20saving?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nautobot_ssot/integrations/aci/signals.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nautobot_ssot/integrations/aci/signals.py b/nautobot_ssot/integrations/aci/signals.py index 57ea0c61..41957b76 100644 --- a/nautobot_ssot/integrations/aci/signals.py +++ b/nautobot_ssot/integrations/aci/signals.py @@ -26,11 +26,12 @@ def _ensure_tag(apps, name, color): ContentType = apps.get_model("contenttypes", "ContentType") tag = apps.get_model("extras", "Tag") _tag = tag.objects.get_or_create(name=name)[0] - _tag.color == color + if _tag.color != color: + _tag.color == color + _tag.validated_save() for content_type in ContentType.objects.all(): if content_type not in _tag.content_types.all(): _tag.content_types.add(content_type) - _tag.validated_save() def aci_create_tag(apps, **kwargs): From c51d7e17a64f591d55bda869146876d3170810a2 Mon Sep 17 00:00:00 2001 From: Eric Fetty Date: Wed, 15 Jan 2025 16:03:49 -0600 Subject: [PATCH 8/9] =?UTF-8?q?fix:=20=F0=9F=90=9B=20disable=20pointless-s?= =?UTF-8?q?tatement=20check=20for=20false=20negative.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nautobot_ssot/integrations/aci/signals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/aci/signals.py b/nautobot_ssot/integrations/aci/signals.py index 41957b76..18d23a97 100644 --- a/nautobot_ssot/integrations/aci/signals.py +++ b/nautobot_ssot/integrations/aci/signals.py @@ -27,7 +27,7 @@ def _ensure_tag(apps, name, color): tag = apps.get_model("extras", "Tag") _tag = tag.objects.get_or_create(name=name)[0] if _tag.color != color: - _tag.color == color + _tag.color == color # pylint: disable=pointless-statement _tag.validated_save() for content_type in ContentType.objects.all(): if content_type not in _tag.content_types.all(): From d866a20999e4483923b81fe67b77253165ec083d Mon Sep 17 00:00:00 2001 From: Eric Fetty Date: Wed, 15 Jan 2025 16:07:50 -0600 Subject: [PATCH 9/9] =?UTF-8?q?fix:=20=F0=9F=90=9B=20correct=20assignment?= =?UTF-8?q?=20operator=20for=20tag=20color=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nautobot_ssot/integrations/aci/signals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nautobot_ssot/integrations/aci/signals.py b/nautobot_ssot/integrations/aci/signals.py index 18d23a97..9d3c1a8b 100644 --- a/nautobot_ssot/integrations/aci/signals.py +++ b/nautobot_ssot/integrations/aci/signals.py @@ -27,7 +27,7 @@ def _ensure_tag(apps, name, color): tag = apps.get_model("extras", "Tag") _tag = tag.objects.get_or_create(name=name)[0] if _tag.color != color: - _tag.color == color # pylint: disable=pointless-statement + _tag.color = color _tag.validated_save() for content_type in ContentType.objects.all(): if content_type not in _tag.content_types.all():