mirror of
https://github.com/netbox-community/netbox.git
synced 2026-01-11 21:10:29 +01:00
Render configuration templates natively #7547
Closed
opened 2025-12-29 20:25:00 +01:00 by adam
·
16 comments
No Branch/Tag Specified
main
update-changelog-comments-docs
feature-removal-issue-type
20911-dropdown
20239-plugin-menu-classes-mutable-state
21097-graphql-id-lookups
feature
fix_module_substitution
20923-dcim-templates
20044-elevation-stuck-lightmode
feature-ip-prefix-link
v4.5-beta1-release
20068-import-moduletype-attrs
20766-fix-german-translation-code-literals
20378-del-script
7604-filter-modifiers-v3
circuit-swap
12318-case-insensitive-uniqueness
20637-improve-device-q-filter
20660-script-load
19724-graphql
20614-update-ruff
14884-script
02496-max-page
19720-macaddress-interface-generic-relation
19408-circuit-terminations-export-templates
20203-openapi-check
fix-19669-api-image-download
7604-filter-modifiers
19275-fixes-interface-bulk-edit
fix-17794-get_field_value_return_list
11507-show-aggregate-and-rir-on-api
9583-add_column_specific_search_field_to_tables
v4.5.0
v4.4.10
v4.4.9
v4.5.0-beta1
v4.4.8
v4.4.7
v4.4.6
v4.4.5
v4.4.4
v4.4.3
v4.4.2
v4.4.1
v4.4.0
v4.3.7
v4.4.0-beta1
v4.3.6
v4.3.5
v4.3.4
v4.3.3
v4.3.2
v4.3.1
v4.3.0
v4.2.9
v4.3.0-beta2
v4.2.8
v4.3.0-beta1
v4.2.7
v4.2.6
v4.2.5
v4.2.4
v4.2.3
v4.2.2
v4.2.1
v4.2.0
v4.1.11
v4.1.10
v4.1.9
v4.1.8
v4.2-beta1
v4.1.7
v4.1.6
v4.1.5
v4.1.4
v4.1.3
v4.1.2
v4.1.1
v4.1.0
v4.0.11
v4.0.10
v4.0.9
v4.1-beta1
v4.0.8
v4.0.7
v4.0.6
v4.0.5
v4.0.3
v4.0.2
v4.0.1
v4.0.0
v3.7.8
v3.7.7
v4.0-beta2
v3.7.6
v3.7.5
v4.0-beta1
v3.7.4
v3.7.3
v3.7.2
v3.7.1
v3.7.0
v3.6.9
v3.6.8
v3.6.7
v3.7-beta1
v3.6.6
v3.6.5
v3.6.4
v3.6.3
v3.6.2
v3.6.1
v3.6.0
v3.5.9
v3.6-beta2
v3.5.8
v3.6-beta1
v3.5.7
v3.5.6
v3.5.5
v3.5.4
v3.5.3
v3.5.2
v3.5.1
v3.5.0
v3.4.10
v3.4.9
v3.5-beta2
v3.4.8
v3.5-beta1
v3.4.7
v3.4.6
v3.4.5
v3.4.4
v3.4.3
v3.4.2
v3.4.1
v3.4.0
v3.3.10
v3.3.9
v3.4-beta1
v3.3.8
v3.3.7
v3.3.6
v3.3.5
v3.3.4
v3.3.3
v3.3.2
v3.3.1
v3.3.0
v3.2.9
v3.2.8
v3.3-beta2
v3.2.7
v3.3-beta1
v3.2.6
v3.2.5
v3.2.4
v3.2.3
v3.2.2
v3.2.1
v3.2.0
v3.1.11
v3.1.10
v3.2-beta2
v3.1.9
v3.2-beta1
v3.1.8
v3.1.7
v3.1.6
v3.1.5
v3.1.4
v3.1.3
v3.1.2
v3.1.1
v3.1.0
v3.0.12
v3.0.11
v3.0.10
v3.1-beta1
v3.0.9
v3.0.8
v3.0.7
v3.0.6
v3.0.5
v3.0.4
v3.0.3
v3.0.2
v3.0.1
v3.0.0
v2.11.12
v3.0-beta2
v2.11.11
v2.11.10
v3.0-beta1
v2.11.9
v2.11.8
v2.11.7
v2.11.6
v2.11.5
v2.11.4
v2.11.3
v2.11.2
v2.11.1
v2.11.0
v2.10.10
v2.10.9
v2.11-beta1
v2.10.8
v2.10.7
v2.10.6
v2.10.5
v2.10.4
v2.10.3
v2.10.2
v2.10.1
v2.10.0
v2.9.11
v2.10-beta2
v2.9.10
v2.10-beta1
v2.9.9
v2.9.8
v2.9.7
v2.9.6
v2.9.5
v2.9.4
v2.9.3
v2.9.2
v2.9.1
v2.9.0
v2.9-beta2
v2.8.9
v2.9-beta1
v2.8.8
v2.8.7
v2.8.6
v2.8.5
v2.8.4
v2.8.3
v2.8.2
v2.8.1
v2.8.0
v2.7.12
v2.7.11
v2.7.10
v2.7.9
v2.7.8
v2.7.7
v2.7.6
v2.7.5
v2.7.4
v2.7.3
v2.7.2
v2.7.1
v2.7.0
v2.6.12
v2.6.11
v2.6.10
v2.6.9
v2.7-beta1
Solcon-2020-01-06
v2.6.8
v2.6.7
v2.6.6
v2.6.5
v2.6.4
v2.6.3
v2.6.2
v2.6.1
v2.6.0
v2.5.13
v2.5.12
v2.6-beta1
v2.5.11
v2.5.10
v2.5.9
v2.5.8
v2.5.7
v2.5.6
v2.5.5
v2.5.4
v2.5.3
v2.5.2
v2.5.1
v2.5.0
v2.4.9
v2.5-beta2
v2.4.8
v2.5-beta1
v2.4.7
v2.4.6
v2.4.5
v2.4.4
v2.4.3
v2.4.2
v2.4.1
v2.4.0
v2.3.7
v2.4-beta1
v2.3.6
v2.3.5
v2.3.4
v2.3.3
v2.3.2
v2.3.1
v2.3.0
v2.2.10
v2.3-beta2
v2.2.9
v2.3-beta1
v2.2.8
v2.2.7
v2.2.6
v2.2.5
v2.2.4
v2.2.3
v2.2.2
v2.2.1
v2.2.0
v2.1.6
v2.2-beta2
v2.1.5
v2.2-beta1
v2.1.4
v2.1.3
v2.1.2
v2.1.1
v2.1.0
v2.0.10
v2.1-beta1
v2.0.9
v2.0.8
v2.0.7
v2.0.6
v2.0.5
v2.0.4
v2.0.3
v2.0.2
v2.0.1
v2.0.0
v2.0-beta3
v1.9.6
v1.9.5
v2.0-beta2
v1.9.4-r1
v1.9.3
v2.0-beta1
v1.9.2
v1.9.1
v1.9.0-r1
v1.8.4
v1.8.3
v1.8.2
v1.8.1
v1.8.0
v1.7.3
v1.7.2-r1
v1.7.1
v1.7.0
v1.6.3
v1.6.2-r1
v1.6.1-r1
1.6.1
v1.6.0
v1.5.2
v1.5.1
v1.5.0
v1.4.2
v1.4.1
v1.4.0
v1.3.2
v1.3.1
v1.3.0
v1.2.2
v1.2.1
v1.2.0
v1.1.0
v1.0.7-r1
v1.0.7
v1.0.6
v1.0.5
v1.0.4
v1.0.3-r1
v1.0.3
1.0.0
Labels
Clear labels
beta
breaking change
complexity: high
complexity: low
complexity: medium
needs milestone
netbox
pending closure
plugin candidate
pull-request
severity: high
severity: low
severity: medium
status: accepted
status: backlog
status: blocked
status: duplicate
status: needs owner
status: needs triage
status: revisions needed
status: under review
topic: GraphQL
topic: Internationalization
topic: OpenAPI
topic: UI/UX
topic: cabling
topic: event rules
topic: htmx navigation
topic: industrialization
topic: migrations
topic: plugins
topic: scripts
topic: templating
topic: testing
type: bug
type: deprecation
type: documentation
type: feature
type: housekeeping
type: translation
Mirrored from GitHub Pull Request
Milestone
No items
No Milestone
Projects
Clear projects
No project
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: starred/netbox#7547
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @jeremystretch on GitHub (Jan 21, 2023).
Originally assigned to: @jeremystretch on GitHub.
NetBox version
v3.4.3
Feature type
New functionality
Proposed functionality
Render device configurations directly from NetBox, using a new
ConfigurationTemplatemodel (detailed below) and both locally- and remotely-sourced context data (see also #11558). Users will be able to fetch rendered configuration templates via both the NetBox UI and APIs.Identifying the appropriate configuration template for a specific device/VM may need further exploration, but an approach similar to what we currently do for config contexts is likely needed. It should also be possible to explicitly define the primary template for any supported object (e.g. by adding a
config_templateForeignKey to the Device and VirtualMachine models).Inclusion tags within a template should work relative to the source file's path within its parent source. We'll need to provide a custom environment overloading the
get_templatemethod to return the appropriate DataFile instance.(I originally considered taking this on as a plugin, however IMO there's a fairly strong case for implementing this functionality natively under the under the "source of truth" umbrella.)
Use case
One of the core functions of network automation involves rendering device configurations from a template (typically written in Jinja2 or a similar language) and contextual data from one or more sources of truth (e.g. NetBox). While this can be accomplished using provisioning tools like Ansible, offering this ability natively within NetBox can simplify the toolchain needed.
Database changes
This proposal would entail the creation of at least one new model, to represent each template. (The
DataFilemodel referenced below is detailed in #11558.)ConfigurationTemplate
name- User-configured namedescriptionlanguage- Template language (Jinja2, possibly others)data_file- Foreign key toDataFile(optional)content- Stores template content if not sourced from a DataFileExternal dependencies
N/A
@renatoalmeidaoliveira commented on GitHub (Jan 30, 2023):
@jeremystretch I think it would be nice to have a "composable" environment for configuration templates, for example:
when deploying a device you can have:
That way having several base templates, and a configuration template that is a composable of the bases may be useful
Another point is how to add variables inside that template, in such way it could be used to render some configuration to deploy a new device or inside a script.
@ryanmerolle commented on GitHub (Feb 2, 2023):
@carlbuchmann, @titom73, @ClausHolbechArista
There might be some good synergies here with ansible avd if you have thoughts.
@jeremystretch commented on GitHub (Feb 8, 2023):
@renatoalmeidaoliveira my intent here is to determine per device the appropriate base template, which can pull in other templates via
{% include %}tags. These inclusion templates can be reused by many templates. This approach has worked very well for me in the past, and mimics NetBox's own template hierarchy.@renatoalmeidaoliveira commented on GitHub (Feb 8, 2023):
Intresting, very similar to the templates environment, that way the user gonna have several "base" templates and for a full configuration he build a template import the base ones.
It seens interesting, but how you gonna import "as a template" some model attribute?
@jeremystretch commented on GitHub (Feb 10, 2023):
So far, I've got the template rendering working as planned, however I'm getting a little hung up on deciding how best to relate devices to specific templates. To review, each device should reference exactly one (if any) configuration template, which can be rendered using context data to produce the desired configuration of that device.
It's entirely possible to designate a single global base template for all devices, and employ logic to evaluate a device's role, platform, etc. to determine which other relevant template to pull in (via
{% include %}tags). However, this is probably not ideal, and I expect that people will want some mechanism native to NetBox for selecting which of several base templates to use for a device. I see a few options, detailed below.Option A: Add a
templateForeignKey to DeviceThis is pretty straightforward: Just add a ForeignKey to the Device model so that each device can point to its appropriate ConfigTemplate. This allows for very efficient queries at the cost of requiring explicit assignment for each device. It's also the safest option, as a misconfiguration will affect only the single device on which it's made.
Option B: Add a
templateForeignKey to DeviceRole and/or PlatformRather than specifying templates per device, we could specify them per device role and/or platform. This would require much less explicit configuration than option A, however we run into an issue if a device's role and platform each indicate a different template. It's also likely users may want to classify devices by some other attribute, such as assigned tag, for the purpose of determining which template to render.
(This option could be combined with option A, where a device's individually-defined template would take precedence over that associated with its role or platform.)
Option C: Add Many-to-Many Assignments on ConfigTemplate
This approaches the problem from a different direction, associating each template with a set of device roles and/or platforms. To determine the appropriate template for a device, a query is made for a template with matching role & platform. (This is similar in concept to how config contexts are retrieved.) This grants a great deal of flexibility, however it would also require some form of tie-breaking mechanism in case multiple matching templates are found.
For example, suppose you associate template A with device role X and template B with platform Y. A device having role X and platform Y would match on both templates. We would need to include a factor such as numeric weighting to prefer one over the other; or return an error.
As with option B, there's a danger here in that a minor change to a template (e.g. removing an assigned role) can break template rendering for a large number of devices; this may be an acceptable drawback considering the flexibility afforded. However, it also complicates retrieving associated device templates in bulk.
This approach could also be combined with option A, which would provide an alternative, explicit assignment for more conservative deployments.
@falz commented on GitHub (Feb 10, 2023):
Fond of Option B but allowing option A to override the role/platform per device seems like the sweet spot to me.
Option C sounds good on paper but seems like excess complexity.
Note that we wrote our own config generator using Netbox, and may have further feedback on this based on our experiences once we see what data is available to the template. Will chime in with more details on that when the time is appropriate.
@zn0k commented on GitHub (Feb 10, 2023):
I concur that option C, while powerful, could get very confusing. Given that the penalty is overwriting the config of a production device and taking it down, simple seems better.
A mixture of options A and B with a slight tweak seems best to me as well. Being able to set defaults via a combination of platform (so we can differentiate between IOS and Junos, for example) and role while retaining the ability to override on a per-device basis by directly assigning a template would be reasonably simple but also allow enough escape hatches to solve slightly trickier situations. I do think it's necessary to allow the combination of platform and role to determine the template - many networks are multi-platform. Or, if you're on Cisco, you're not very unlikely to run multiple dialects between legacy and newer devices.
@PieterL75 commented on GitHub (Feb 10, 2023):
I would like to be able to run multiple templates to a device.
An ofcourse, each template has to be valid for that vendor/syntax.
imo, this should only create a config out of a template, but never deploy it direct.
That does not seems like the task of NetBox
@jeremystretch commented on GitHub (Feb 10, 2023):
You can do this by creating a base template which includes other (reusable) templates, in the desired order and subject to any logic asserting specific device attributes. For example:
You'll likely have different base templates for each role/platform.
I also want to point out that you do not need to create a corresponding ConfigTemplate instance in NetBox to accomplish this: Included templates can be populated directly from other remotely-sourced data files. You'll only need to create a ConfigTemplate for each template that you want to render directly.
100% 👍 - There are plenty of other tools for that.
@ryanmerolle commented on GitHub (Feb 10, 2023):
Not trying to pile on, but just share a current workflow to broaden an understanding of how users currently approach.
I currently do this off box, and my templates get applied to a "function" and platform. Functions are assigned to device roles (the netbox model). Here are a few examples:
I think map my made up functions to NetBox Device Roles like:
All of this is defined by using include templates like @jeremystretch mentioned. "Functions" are not really modeled in netbox, but in the templates that define each device role. All of the above templates are created as needed, and if I bring up a JUNOS border_leaf in the future, the template would fail (as it should) until platform specific templates are created for all the boarder_leaf functions.
I probably would continue to do this off box because I produce additional artifacts and upload all to git:
@ryanmerolle commented on GitHub (Feb 10, 2023):
Oh I forgot to add, I feel like the Option C, similar to how config_context can be applied ultimate gives use the most flexibility, but its likely a trade off with complexity/confusion.
@jeremystretch commented on GitHub (Feb 10, 2023):
For now, I've just added the foreign key from Device to ConfigTemplate, since it seems like we'll almost certainly want the ability to specify an explicit assignment regardless. Making really great progress with this already!
@davidgwatkins commented on GitHub (Feb 12, 2023):
This is really awesome progress! Any chance that could be modified to be Device to Many? We have J2 templates that are CLI for Day 0 / out-of-band / sneakernet, then NETCONF for Day 2 use cases; which gets rendered is based on device status. Perhaps this is covered under the use case for multiple component templates, but we are already using includes.
@jeremystretch commented on GitHub (Feb 17, 2023):
Pretty happy with where this ended up. No doubt we'll continue to refine & improve the implementation from here, but I'm calling it done for the purposes of this particular FR.
You'll be able to implement conditional logic within the template itself, which could (for example) check for the presence of a flag indicating which type of config to render, and pull in the relevant subordinate template files.
@dmulyalin commented on GitHub (Mar 25, 2023):
This is great.
Late to the party, but would like to share an idea.
It would be good to associate config templates with services as well. Say service L3VPN for customer assigned to the device, service has template associated matching device platform to produce requied configuration.
@jonasnieberle commented on GitHub (May 6, 2023):
@jeremystretch : Do you have an overview of the device and interface object, which you can use in the Jinja2 Configuration Templates?
For example:
Device:
{{ device.name }} --> working: print device name
{{ device.url }} --> not working: should print url?
{{ device.serial }} --> working: print sn
Interfaces:
{% for interface in device.interfaces.all() %}
{{ interface }} --> working: print interface name
{{ interface.enabled }} --> working: print interface enabled value
{% endfor %}
Custom Fields:
Can you also access the custom fields of an interface / device?
I try serveral methods to get an overview of all attributes / values / keys of the object ... but not working
{{ device.keys() }} / {{ device.values() }} / {{ device.attr() }}
Access netbox data:
I think it would also be a very nice feature, if you can access the complete netbox data via jinja2 templates.
For example:
Maybe it is already possible and I dont know how?