Quellcode durchsuchen

Merge branch 'develop' into develop-2.10

Jeremy Stretch vor 5 Jahren
Ursprung
Commit
a371c08c86

+ 3 - 5
.github/ISSUE_TEMPLATE/bug_report.md

@@ -7,11 +7,9 @@ about: Report a reproducible bug in the current release of NetBox
 <!--
     NOTE: IF YOUR ISSUE DOES NOT FOLLOW THIS TEMPLATE, IT WILL BE CLOSED.
 
-    This form is only for reproducible bugs. If you need assistance with
-    NetBox installation, or if you have a general question, DO NOT open an
-    issue. Instead, post to our mailing list:
-
-        https://groups.google.com/g/netbox-discuss
+    This form is only for reporting reproducible bugs. If you need assistance
+    with NetBox installation, or if you have a general question, please start a
+    discussion instead: https://github.com/netbox-community/netbox/discussions
 
     Please describe the environment in which you are running NetBox. Be sure
     that you are running an unmodified instance of the latest stable release

+ 2 - 4
.github/ISSUE_TEMPLATE/feature_request.md

@@ -8,10 +8,8 @@ about: Propose a new NetBox feature or enhancement
     NOTE: IF YOUR ISSUE DOES NOT FOLLOW THIS TEMPLATE, IT WILL BE CLOSED.
 
     This form is only for proposing specific new features or enhancements.
-    If you have a general idea or question, please post to our mailing list
-    instead of opening an issue:
-
-        https://groups.google.com/g/netbox-discuss
+    If you have a general idea or question, please start a discussion instead:
+    https://github.com/netbox-community/netbox/discussions
 
     NOTE: Due to an excessive backlog of feature requests, we are not currently
     accepting any proposals which significantly extend NetBox's feature scope.

+ 9 - 6
README.md

@@ -37,18 +37,21 @@ or join us in the **#netbox** Slack channel on [NetworkToCode](https://networkto
 ## Installation
 
 Please see [the documentation](http://netbox.readthedocs.io/en/stable/) for
-instructions on installing NetBox. To upgrade NetBox, please download the [latest release](https://github.com/netbox-community/netbox/releases)
-and run `upgrade.sh`.
+instructions on installing NetBox. To upgrade NetBox, please download the
+[latest release](https://github.com/netbox-community/netbox/releases) and
+run `upgrade.sh`.
 
 ## Providing Feedback
 
-Feature requests and bug reports must be submitted as GiHub issues. (Please be
-sure to use the [appropriate template](https://github.com/netbox-community/netbox/issues/new/choose).)
-For general discussion, please consider joining our [mailing list](https://groups.google.com/g/netbox-discuss).
+The best platform for general feedback, assistance, and other discussion is our
+[GitHub discussions](https://github.com/netbox-community/netbox/discussions).
+To report a bug or request a specific feature, please open a GitHub issue using
+the [appropriate template](https://github.com/netbox-community/netbox/issues/new/choose).
 
 If you are interested in contributing to the development of NetBox, please read
 our [contributing guide](CONTRIBUTING.md) prior to beginning any work.
 
 ## Related projects
 
-Please see [our wiki](https://github.com/netbox-community/netbox/wiki/Community-Contributions) for a list of relevant community projects.
+Please see [our wiki](https://github.com/netbox-community/netbox/wiki/Community-Contributions)
+for a list of relevant community projects.

+ 2 - 1
docs/development/index.md

@@ -7,7 +7,8 @@ NetBox is maintained as a [GitHub project](https://github.com/netbox-community/n
 Communication among developers should always occur via public channels:
 
 * [GitHub issues](https://github.com/netbox-community/netbox/issues) - All feature requests, bug reports, and other substantial changes to the code base **must** be documented in an issue.
-* [The mailing list](https://groups.google.com/g/netbox-discuss) - The preferred forum for general discussion and support issues. Ideal for shaping a feature request prior to submitting an issue.
+* [GitHub discussions](https://github.com/netbox-community/netbox/discussions) - The preferred forum for general discussion and support issues. Ideal for shaping a feature request prior to submitting an issue.
+* [The mailing list](https://groups.google.com/g/netbox-discuss) - An alternative forum for general discussion (GitHub is preferred).
 * [#netbox on NetworkToCode](http://slack.networktocode.com/) - Good for quick chats. Avoid any discussion that might need to be referenced later on, as the chat history is not retained long.
 
 ## Governance

+ 5 - 1
docs/release-notes/version-2.9.md

@@ -1,19 +1,23 @@
 # NetBox v2.9
 
-## v2.9.11 (FUTURE)
+## v2.9.11 (2020-12-11)
 
 ### Enhancements
 
 * [#5424](https://github.com/netbox-community/netbox/issues/5424) - Allow passing Python code to `nbshell` using `--command`
+* [#5439](https://github.com/netbox-community/netbox/issues/5439) - Add CS and SN fiber port types
 
 ### Bug Fixes
 
 * [#5383](https://github.com/netbox-community/netbox/issues/5383) - Fix setting user password via REST API
 * [#5396](https://github.com/netbox-community/netbox/issues/5396) - Fix uniqueness constraint for virtual machine names
+* [#5387](https://github.com/netbox-community/netbox/issues/5387) - Fix error when rendering config contexts when objects have multiple tags assigned
 * [#5407](https://github.com/netbox-community/netbox/issues/5407) - Add direct link to secret on secrets list
 * [#5408](https://github.com/netbox-community/netbox/issues/5408) - Fix updating secrets without setting new plaintext
 * [#5410](https://github.com/netbox-community/netbox/issues/5410) - Restore tags field on cable connection forms
+* [#5433](https://github.com/netbox-community/netbox/issues/5433) - Exclude SVG files from front/rear image upload for device types (currently unsupported)
 * [#5436](https://github.com/netbox-community/netbox/issues/5436) - Show assigned IP addresses in interfaces list
+* [#5446](https://github.com/netbox-community/netbox/issues/5446) - Fix validation for plugin version and required settings
 
 ---
 

+ 4 - 0
netbox/dcim/choices.py

@@ -887,6 +887,8 @@ class PortTypeChoices(ChoiceSet):
     TYPE_LSH = 'lsh'
     TYPE_LSH_APC = 'lsh-apc'
     TYPE_SPLICE = 'splice'
+    TYPE_CS = 'cs'
+    TYPE_SN = 'sn'
 
     CHOICES = (
         (
@@ -914,6 +916,8 @@ class PortTypeChoices(ChoiceSet):
                 (TYPE_SC, 'SC'),
                 (TYPE_SC_APC, 'SC/APC'),
                 (TYPE_ST, 'ST'),
+                (TYPE_CS, 'CS'),
+                (TYPE_SN, 'SN'),
                 (TYPE_SPLICE, 'Splice'),
             )
         )

+ 8 - 1
netbox/dcim/forms.py

@@ -922,7 +922,14 @@ class DeviceTypeForm(BootstrapMixin, CustomFieldModelForm):
             'front_image', 'rear_image', 'comments', 'tags',
         ]
         widgets = {
-            'subdevice_role': StaticSelect2()
+            'subdevice_role': StaticSelect2(),
+            # Exclude SVG images (unsupported by PIL)
+            'front_image': forms.FileInput(attrs={
+                'accept': 'image/bmp,image/gif,image/jpeg,image/png,image/tiff'
+            }),
+            'rear_image': forms.FileInput(attrs={
+                'accept': 'image/bmp,image/gif,image/jpeg,image/png,image/tiff'
+            })
         }
 
 

+ 2 - 3
netbox/extras/plugins/__init__.py

@@ -3,7 +3,6 @@ import inspect
 from packaging import version
 
 from django.apps import AppConfig
-from django.conf import settings
 from django.core.exceptions import ImproperlyConfigured
 from django.template.loader import get_template
 
@@ -71,10 +70,10 @@ class PluginConfig(AppConfig):
             register_menu_items(self.verbose_name, menu_items)
 
     @classmethod
-    def validate(cls, user_config):
+    def validate(cls, user_config, netbox_version):
 
         # Enforce version constraints
-        current_version = version.parse(settings.VERSION)
+        current_version = version.parse(netbox_version)
         if cls.min_version is not None:
             min_version = version.parse(cls.min_version)
             if current_version < min_version:

+ 16 - 1
netbox/extras/querysets.py

@@ -1,5 +1,6 @@
 from django.db.models import OuterRef, Subquery, Q
 
+from extras.models.tags import TaggedItem
 from utilities.query_functions import EmptyGroupByJSONBAgg, OrderableJSONBAgg
 from utilities.querysets import RestrictedQuerySet
 
@@ -81,11 +82,25 @@ class ConfigContextModelQuerySet(RestrictedQuerySet):
 
     def _get_config_context_filters(self):
         # Construct the set of Q objects for the specific object types
+        tag_query_filters = {
+            "object_id": OuterRef(OuterRef('pk')),
+            "content_type__app_label": self.model._meta.app_label,
+            "content_type__model": self.model._meta.model_name
+        }
         base_query = Q(
             Q(platforms=OuterRef('platform')) | Q(platforms=None),
             Q(tenant_groups=OuterRef('tenant__group')) | Q(tenant_groups=None),
             Q(tenants=OuterRef('tenant')) | Q(tenants=None),
-            Q(tags=OuterRef('tags')) | Q(tags=None),
+            Q(
+                tags__pk__in=Subquery(
+                    TaggedItem.objects.filter(
+                        **tag_query_filters
+                    ).values_list(
+                        'tag_id',
+                        flat=True
+                    )
+                )
+            ) | Q(tags=None),
             is_active=True,
         )
 

+ 43 - 0
netbox/extras/tests/test_models.py

@@ -321,3 +321,46 @@ class ConfigContextTest(TestCase):
         annotated_queryset = Device.objects.filter(name=device.name).annotate_config_context_data()
         self.assertEqual(ConfigContext.objects.get_for_object(device).count(), 1)
         self.assertEqual(device.get_config_context(), annotated_queryset[0].get_config_context())
+
+    def test_multiple_tags_return_distinct_objects_with_seperate_config_contexts(self):
+        """
+        Tagged items use a generic relationship, which results in duplicate rows being returned when queried.
+        This is combatted by by appending distinct() to the config context querysets. This test creates a config
+        context assigned to two tags and ensures objects related by those same two tags result in only a single
+        config context record being returned.
+
+        This test case is seperate from the above in that it deals with multiple config context objects in play.
+
+        See https://github.com/netbox-community/netbox/issues/5387
+        """
+        tag_context_1 = ConfigContext.objects.create(
+            name="tag-1",
+            weight=100,
+            data={
+                "tag": 1
+            }
+        )
+        tag_context_1.tags.add(self.tag)
+        tag_context_2 = ConfigContext.objects.create(
+            name="tag-2",
+            weight=100,
+            data={
+                "tag": 1
+            }
+        )
+        tag_context_2.tags.add(self.tag2)
+
+        device = Device.objects.create(
+            name="Device 3",
+            site=self.site,
+            tenant=self.tenant,
+            platform=self.platform,
+            device_role=self.devicerole,
+            device_type=self.devicetype
+        )
+        device.tags.add(self.tag)
+        device.tags.add(self.tag2)
+
+        annotated_queryset = Device.objects.filter(name=device.name).annotate_config_context_data()
+        self.assertEqual(ConfigContext.objects.get_for_object(device).count(), 2)
+        self.assertEqual(device.get_config_context(), annotated_queryset[0].get_config_context())

+ 6 - 8
netbox/extras/tests/test_plugins.py

@@ -86,21 +86,19 @@ class PluginTest(TestCase):
         """
         self.assertIn('extras.tests.dummy_plugin.*', settings.CACHEOPS)
 
-    @override_settings(VERSION='0.9')
     def test_min_version(self):
         """
         Check enforcement of minimum NetBox version.
         """
         with self.assertRaises(ImproperlyConfigured):
-            dummy_config.validate({})
+            dummy_config.validate({}, '0.9')
 
-    @override_settings(VERSION='10.0')
     def test_max_version(self):
         """
         Check enforcement of maximum NetBox version.
         """
         with self.assertRaises(ImproperlyConfigured):
-            dummy_config.validate({})
+            dummy_config.validate({}, '10.0')
 
     def test_required_settings(self):
         """
@@ -110,11 +108,11 @@ class PluginTest(TestCase):
             required_settings = ['foo']
 
         # Validation should pass when all required settings are present
-        DummyConfigWithRequiredSettings.validate({'foo': True})
+        DummyConfigWithRequiredSettings.validate({'foo': True}, settings.VERSION)
 
         # Validation should fail when a required setting is missing
         with self.assertRaises(ImproperlyConfigured):
-            DummyConfigWithRequiredSettings.validate({})
+            DummyConfigWithRequiredSettings.validate({}, settings.VERSION)
 
     def test_default_settings(self):
         """
@@ -127,10 +125,10 @@ class PluginTest(TestCase):
 
         # Populate the default value if setting has not been specified
         user_config = {}
-        DummyConfigWithDefaultSettings.validate(user_config)
+        DummyConfigWithDefaultSettings.validate(user_config, settings.VERSION)
         self.assertEqual(user_config['bar'], 123)
 
         # Don't overwrite specified values
         user_config = {'bar': 456}
-        DummyConfigWithDefaultSettings.validate(user_config)
+        DummyConfigWithDefaultSettings.validate(user_config, settings.VERSION)
         self.assertEqual(user_config['bar'], 456)

+ 1 - 1
netbox/netbox/settings.py

@@ -609,7 +609,7 @@ for plugin_name in PLUGINS:
     # Validate user-provided configuration settings and assign defaults
     if plugin_name not in PLUGINS_CONFIG:
         PLUGINS_CONFIG[plugin_name] = {}
-    plugin_config.validate(PLUGINS_CONFIG[plugin_name])
+    plugin_config.validate(PLUGINS_CONFIG[plugin_name], VERSION)
 
     # Add middleware
     plugin_middleware = plugin_config.middleware