1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Closes #2495: Enable deep-merging of config context data

This commit is contained in:
Jeremy Stretch
2018-12-05 14:34:49 -05:00
parent d3d6c83fbb
commit 686a65880e
4 changed files with 108 additions and 4 deletions

View File

@ -3,6 +3,7 @@ v2.4.9 (FUTURE)
## Enhancements
* [#2089](https://github.com/digitalocean/netbox/issues/2089) - Add SONET interface form factors
* [#2495](https://github.com/digitalocean/netbox/issues/2495) - Enable deep-merging of config context data
* [#2597](https://github.com/digitalocean/netbox/issues/2597) - Add FibreChannel SFP28 (32GFC) interface form factor
## Bug Fixes

View File

@ -18,7 +18,7 @@ from django.utils.encoding import python_2_unicode_compatible
from django.utils.safestring import mark_safe
from dcim.constants import CONNECTION_STATUS_CONNECTED
from utilities.utils import foreground_color
from utilities.utils import deepmerge, foreground_color
from .constants import *
from .querysets import ConfigContextQuerySet
@ -727,11 +727,11 @@ class ConfigContextModel(models.Model):
# Compile all config data, overwriting lower-weight values with higher-weight values where a collision occurs
data = OrderedDict()
for context in ConfigContext.objects.get_for_object(self):
data.update(context.data)
data = deepmerge(data, context.data)
# If the object has local config context data defined, that data overwrites all rendered data
# If the object has local config context data defined, merge it last
if self.local_context_data is not None:
data.update(self.local_context_data)
data = deepmerge(data, self.local_context_data)
return data

View File

@ -0,0 +1,89 @@
from django.test import TestCase
from utilities.utils import deepmerge
class DeepMergeTest(TestCase):
"""
Validate the behavior of the deepmerge() utility.
"""
def setUp(self):
return
def test_deepmerge(self):
dict1 = {
'active': True,
'foo': 123,
'fruits': {
'orange': 1,
'apple': 2,
'pear': 3,
},
'vegetables': None,
'dairy': {
'milk': 1,
'cheese': 2,
},
'deepnesting': {
'foo': {
'a': 10,
'b': 20,
'c': 30,
},
},
}
dict2 = {
'active': False,
'bar': 456,
'fruits': {
'banana': 4,
'grape': 5,
},
'vegetables': {
'celery': 1,
'carrots': 2,
'corn': 3,
},
'dairy': None,
'deepnesting': {
'foo': {
'a': 100,
'd': 40,
},
},
}
merged = {
'active': False,
'foo': 123,
'bar': 456,
'fruits': {
'orange': 1,
'apple': 2,
'pear': 3,
'banana': 4,
'grape': 5,
},
'vegetables': {
'celery': 1,
'carrots': 2,
'corn': 3,
},
'dairy': None,
'deepnesting': {
'foo': {
'a': 100,
'b': 20,
'c': 30,
'd': 40,
},
},
}
self.assertEqual(
deepmerge(dict1, dict2),
merged
)

View File

@ -1,5 +1,6 @@
from __future__ import unicode_literals
from collections import OrderedDict
import datetime
import json
import six
@ -109,3 +110,16 @@ def serialize_object(obj, extra=None):
data.update(extra)
return data
def deepmerge(original, new):
"""
Deep merge two dictionaries (new into original) and return a new dict
"""
merged = OrderedDict(original)
for key, val in new.items():
if key in original and isinstance(original[key], dict) and isinstance(val, dict):
merged[key] = deepmerge(original[key], val)
else:
merged[key] = val
return merged