Puppet is IT automation software that helps system administrators manage infrastructure throughout its lifecycle, from provisioning and configuration to orchestration and reporting. Puppet for Junos OS adds Juniper Networks equipment support and functionality.
You typically deploy the Puppet software using a client-server arrangement, where the server, or Puppet master, manages one or more agent nodes. The client daemon, or Puppet agent, runs on each of the managed compute resources. You create Puppet manifest files to describe your desired system configuration. The Puppet master compiles the manifests into catalogs, and the Puppet agent periodically retrieves the catalog and applies the necessary changes to the configuration. Juniper Networks provides support for using Puppet to manage certain devices running the Junos® operating system (Junos OS).
Netdev is a vendor-neutral network abstraction framework developed by Juniper Networks and contributed freely to the DevOps community. The netdev_stdlib Puppet module provides new Puppet resource types for configuring certain hierarchies of Junos configuration like physical interfaces, LAGs, VLANs. Anytime something new needs to be automated beside defined resource types in netdev module, new resource types needs to defined and implemented. This process can be a very lengthy process (not really scalable). Anytime new resource is added, new netdev module needs to be installed. To solve these problems we implemented a generic resource, which allows automating anything in Junos configuration without extending existing netdev module anymore.
This magic generic resource called “apply-group” resource and is based on ERB templates and day-1 Junos feature called apply-group. What is ERB template? ERB template is part of Ruby standard library and it allows generating any kind of text from templates. The templates combine plain text with Ruby code for variable substitution, which makes them easy to write and maintain. Detailed information on ERB templates is available on Puppet homepage: https://docs.puppetlabs.com/guides/templating.html.
Junos “apply-groups” define common configuration snippets in one part of the configuration, which you then apply/inherit in other parts of configuration. This allows defining common portions of the configuration once and having them apply in many places in the configuration, thus minimizing or eliminating the risk of configuration inconsistencies or errors. Picture below shows one possible use case:
Now let us take an example of BGP resource that does not exists as part of netdev Puppet library and see how we can automate it using “apply-group” netdev resource.
In a first step I just configured one BGP group manually in CLI. There are multiple ways how you can show existing configuration in Junos: XML, as a collection of “set” commands, native hierarchical Junos output, JSON. First 3 options are showed in the screenshot below:
In the next step I create a new ERB template called bgp.text.erb under /etc/puppet/modules/netdev_stdlib_junos/templates. ERB template can be in 3 different formats (corresponding to Junos output formats): name.XML.erb, name.SET.erb, name.TEXT.erb. Let me start with TEXT example. I just copy the output from Junos device, paste it into body of ERB template and replace all variable parts (in this example group name, local-address, peer-as, list of neighbor addresses) with variables.
Tags <%...%> are processed by ERB processor. ERB template called with variables (in this example variable name is bgp) which are defined in a Puppet manifest. bgp variable in this example is a hash, which takes BGP group name as a key, and another hash as a value. Entire concept is very similar to Jinja templates.
bgp hash structure correlates to the structure of variable statements in BGP configuration:
- You can have multiple groups defined under BGP (named in this example “internal” and “external”)
- Each of these groups have a set of variables (neighbor, local-address, peer-as, type)
- You can have multiple neighbors within same group (array is used as a value of “neighbor” key)
“active” parameter passed into apply-group can have 2 values: true or false. If set to “true” apply-group will be activated, if set to “false” it will not get applied but you will still see group itself in the configuration. “ensure” take either “present” or “absent” value. If set to “present” the group will be visible under “groups” hierarchy, if set to “absent” it will be deleted.
Now we can do a Puppet run on our QFX5100 by executing “puppet agent –test”:
Output above shows that new group called bgp_group was configured and applied on QFX5100. It is now easy to define another ERB template in different format (e.g. as a bgp.set.erb):
Or in bgp.xml.erb format:
Obviously all of these ERB templates get the same bgp hash variable defined in Puppet manifest file.
Approach discussed in this blog allows you to automate easily anything inside Junos configuration without ever requiring extension in netdev module. It can be freely downloaded under https://forge.puppetlabs.com/juniper/netdev_stdlib_junos und used without any license. As Chef is using Ruby, we will support same approach for Chef in the future as well.