Advanced Config Template Tricks
February 05, 2024
The rXg provides a mechanism for providing configuration in the form of a YAML document. These YAML documents are called Config Templates.
The ability to upload and execute Config Templates, as well as a simple set of examples are provided under System -> Backup.
A Simple Example
This template would either create an Account Group named "Test" and assign it a priority of 4, or would find an existing Account Group named "Test" and change its priority to 4. I.e., the first key/value pair in an object is used as the lookup.
The key of the top-level YAML describes the model name and can be in singular PascalCase (e.g., AccountGroup) or plural snake_case (e.g., account_groups).
account_groups: - name: Test priority: 4
ERB
Config Templates may use ERB to dynamically generate YAML, however you should take care to not created/update/delete objects in ERB, as the ERB is executed during Config Template validation.
If you run console inside an rXg, you can execute this ERB manually to see the output:
networks = ["net1", "net2"] vlans = [11, 12] template = <<~TEMPLATE vlans: <% networks.each do |network|%> - name: <%= network%> interface: em0 <% vlans.each do |vlan|%> tag: <%= vlan %> <% end %> <% end %> TEMPLATE puts ERB.new(template).result_with_hash({networks: networks, vlans: vlans})
Composition
You can include one template in another using the ConfigTemplate.include_template directive:
<%= ConfigTemplate.include_template(file: '01_initial.yml.erb', context: binding) %>
You must pass either a file, record, or url to provide the source of the template, and you must include the binding context if you wish to override variables in the included template.
Another important point for composing templates is that YAML allows the top-level data structure to be either a list or a dictionary. While using a dictionary at the top-level can be more readable, a list is more flexible when it comes to composing Config Templates.
As an example, see how an included Config Template can inadvertently override the configuration of the parent:
a.yml:
account_groups: - name: Internal priority: 4
b.yml:
account_groups: - name: Public priority: 6 <%= ConfigTemplate.include_template(url: 'https://example.com/a.yml', context: binding) %>
If you were to execute b.yml, only the Internal Account Group would be created, since the two account_groups keys would conflict, and the latter would overwrite the former.
To resolve this, you can make the top-level data structure a list:
a.yml:
- account_groups: - name: Internal priority: 4
b.yml:
- account_groups: - name: Public priority: 6 <%= ConfigTemplate.include_template(url: 'https://example.com/a.yml', context: binding) %>
Now, both Account Groups would get created, at the cost of a little more indentation.