Allow Config Contexts to be deep merged #2048

Closed
opened 2025-12-29 17:21:45 +01:00 by adam · 7 comments
Owner

Originally created by @martink2 on GitHub (Oct 6, 2018).

Environment

  • Python version: 3.5.2
  • NetBox version: 2.4.5

Proposed Functionality

Netbox allows Context data to be provided in a hierarchical fashion via JSON
and also allows merging multiple Contexts. The current merge overrides the
entire subtree if a later Context includes the same keys. For large organised
Context data it would be more desirable to merge not only based on "top level"
keys but also merge further down in the key hierarchy by performing a deep merge
as many YAML/JSON config based automation tools like Chef or Ansible do.

Use Case

Use deep merged JSON config directly in Ansible or Chef.
Example of desired Behaviour:
Context1

{
    "cc": {
        "net": {
            "vrf": {
                "cc-cloud01": {
                    "global-rt-export": [
                        101
                    ]
            }
        }
    }
}

Context 2

{
    "cc": {
        "net": {
            "vpn_asn": 65126
        }
    }
}

Current Result

{
    "cc": {
        "net": {
            "vpn_asn": 65126
        }
    }
}

Desired Result

{
    "cc": {
        "net": {
            "vpn_asn": 65126,
            "vrf": {
                "cc-cloud01": {
                    "global-rt-export": [
                        101
                    ]
            }
        }
    }
}

Database Changes

None

External Dependencies

None

Originally created by @martink2 on GitHub (Oct 6, 2018). <!-- NOTE: 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/forum/#!forum/netbox-discuss NOTE: Due to an excessive backlog of feature requests, we are not currently accepting any proposals which significantly extend NetBox's feature scope. Please describe the environment in which you are running NetBox. Be sure that you are running an unmodified instance of the latest stable release before submitting a bug report. --> ### Environment * Python version: 3.5.2 * NetBox version: 2.4.5 <!-- Describe in detail the new functionality you are proposing. Include any specific changes to work flows, data models, or the user interface. --> ### Proposed Functionality Netbox allows Context data to be provided in a hierarchical fashion via JSON and also allows merging multiple Contexts. The current merge overrides the entire subtree if a later Context includes the same keys. For large organised Context data it would be more desirable to merge not only based on "top level" keys but also merge further down in the key hierarchy by performing a deep merge as many YAML/JSON config based automation tools like Chef or Ansible do. <!-- Convey an example use case for your proposed feature. Write from the perspective of a NetBox user who would benefit from the proposed functionality and describe how. ---> ### Use Case Use deep merged JSON config directly in Ansible or Chef. Example of desired Behaviour: Context1 ```json { "cc": { "net": { "vrf": { "cc-cloud01": { "global-rt-export": [ 101 ] } } } } ``` Context 2 ```json { "cc": { "net": { "vpn_asn": 65126 } } } ``` Current Result ```json { "cc": { "net": { "vpn_asn": 65126 } } } ``` Desired Result ```json { "cc": { "net": { "vpn_asn": 65126, "vrf": { "cc-cloud01": { "global-rt-export": [ 101 ] } } } } ``` <!-- Note any changes to the database schema necessary to support the new feature. For example, does the proposal require adding a new model or field? (Not all new features require database changes.) ---> ### Database Changes None <!-- List any new dependencies on external libraries or services that this new feature would introduce. For example, does the proposal require the installation of a new Python package? (Not all new features introduce new dependencies.) --> ### External Dependencies None
adam added the status: acceptedtype: feature labels 2025-12-29 17:21:45 +01:00
adam closed this issue 2025-12-29 17:21:45 +01:00
Author
Owner

@jeremystretch commented on GitHub (Oct 9, 2018):

In this example, how would a user replace the contents of net?

@jeremystretch commented on GitHub (Oct 9, 2018): In this example, how would a user _replace_ the contents of `net`?
Author
Owner

@martink2 commented on GitHub (Oct 9, 2018):

In chef (im am using this example as i am most familiar with that one) the idea is one does
not. Dicts are only used to structure data so values are the leafs of the config tree and you can
replace any of those by just setting them to something different or null.

You could force this in the example by setting:

{
    "cc": {
        "net": null
        }
    }
}

and

{
    "cc": {
        "net": {
            "abc": 126
        }
    }
}

which would leave you with an "override"
another option would be to introduce a setting
on the context itself if it should be handled
as "merge" or "override". The library used in
the PR would make that easy to implement.

@martink2 commented on GitHub (Oct 9, 2018): In chef (im am using this example as i am most familiar with that one) the idea is one does not. Dicts are only used to structure data so values are the leafs of the config tree and you can replace any of those by just setting them to something different or null. You could force this in the example by setting: ```json { "cc": { "net": null } } } ``` and ``` { "cc": { "net": { "abc": 126 } } } ``` which would leave you with an "override" another option would be to introduce a setting on the context itself if it should be handled as "merge" or "override". The library used in the PR would make that easy to implement.
Author
Owner

@cimnine commented on GitHub (Oct 9, 2018):

In this example, how would a user replace the contents of net?

I'm wondering what the concrete use-case would be for this?

@cimnine commented on GitHub (Oct 9, 2018): > In this example, how would a user replace the contents of net? I'm wondering what the concrete use-case would be for this?
Author
Owner

@jeremystretch commented on GitHub (Oct 9, 2018):

I'm wondering what the concrete use-case would be for this?

Removing a widely applicable piece of data only for a small subset of devices, such as in a lab or other niche area or role. It's a function that NetBox supports today, so every effort should be made to preserve it.

another option would be to introduce a setting on the context itself if it should be handled as "merge" or "override".

This would probably be the preferred approach. We can introduce a boolean field on the ConfigContext model to specify the behavior, defaulting to merge.

@jeremystretch commented on GitHub (Oct 9, 2018): > I'm wondering what the concrete use-case would be for this? Removing a widely applicable piece of data only for a small subset of devices, such as in a lab or other niche area or role. It's a function that NetBox supports today, so every effort should be made to preserve it. > another option would be to introduce a setting on the context itself if it should be handled as "merge" or "override". This would probably be the preferred approach. We can introduce a boolean field on the ConfigContext model to specify the behavior, defaulting to merge.
Author
Owner

@lampwins commented on GitHub (Oct 9, 2018):

Just a note for when it comes time to implement this, the same boolean field will need to be added to the Device and VirtualMachine models by way of the ConfigContextModel. This is unless we want the local_context_data to only every use one method (merge or replace), which I don't think makes much sense.

@lampwins commented on GitHub (Oct 9, 2018): Just a note for when it comes time to implement this, the same boolean field will need to be added to the Device and VirtualMachine models by way of the ConfigContextModel. This is unless we want the `local_context_data` to only every use one method (merge or replace), which I don't _think_ makes much sense.
Author
Owner

@sdktr commented on GitHub (Oct 15, 2018):

is there a specific reason that the local config context doesn't use the generic ConfigContextModel?

@sdktr commented on GitHub (Oct 15, 2018): is there a specific reason that the local config context doesn't use the generic ```ConfigContextModel```?
Author
Owner

@jeremystretch commented on GitHub (Nov 5, 2018):

@sdktr local config context is one-to-one: It would be much less efficient to store a separate ConfigContextModel instance for every device.

@jeremystretch commented on GitHub (Nov 5, 2018): @sdktr local config context is one-to-one: It would be much less efficient to store a separate `ConfigContextModel` instance for every device.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#2048