OpenNetAdmin

Search:   

template_merge

What is template_merge

Template_merge is a perl program that allows you to output text based files that are the result of a parameterized template that is merged with various anchor types. It is useful for creating generic templates that can be merged to create site or job specific files to be used by downstream processes.

The classic case would be to create a template for your Cisco IOS configuration. You could start by doing a “show run” on a device. You would then determine each portion of the config that will change from device to device. Those portions would be replaced with an appropriate anchor that will get its value from another location such as an upstream database. This would now allow you to execute a template_merge that can output a device specific configuration for any number of similarly configured IOS devices.

Take the following IOS config example:

! This config was created on $[cmdx:date] by $[env:LOGNAME]
!
hostname $[parm:ROUTER_NAME]
!
ip name-server $[dns:ns1.yoursite.com]
ip name-server $[dns:ns2.yoursite.com]
ip ssh version 2
!
no ip http server
!
logging $[parm:LOGSERVER1]
logging $[parm:LOGSERVER2]
!
interface FastEthernet0/1
 description $[parm:DESKTOP_VLAN_DESC]
 ip address $[parm:DESKTOP_VLAN_GATEWAY_IP] $[parm:DESKTOP_VLAN_MASK]

This would output the following once merged, assuming an appropriate parm file had been extracted from a database providing these values:

! This config was created on Wed Dec 20 11:16:07 MST 2006 by root
!
hostname router-a
!
ip name-server 10.1.1.1
ip name-server 10.2.2.2
ip ssh version 2
!
no ip http server
!
logging 10.4.4.1
logging 10.4.4.2
!
interface FastEthernet0/1
 description VLAN_DESKTOP_USERS_001
 ip address 10.10.10.1 255.255.255.0

Using the -o option the output could be written to /tftpboot/router-a.cfg and then tftped into the device on bootup or used by an config update script.

Installation

Requirements

The unix host utility is used to do dns lookups when using the $[dns:xxx] option. It must be in your path and a proper /etc/resolv.conf file for the names you intend to look up.

template_merge is a perl script/program, and only needs to be copied to a directory in your path to make it accessible. Most likely the following steps will be sufficient:

  1. Extract the package
    tar -zxvf template_merge-v1.XX.tar.gz
  2. Copy the template_merge script to /usr/local/bin or equivalent
    cp template_merge-v1.XX/template_merge /usr/local/bin
  3. Make sure its executable
    chmod +x /usr/local/bin/template_merge
  4. Run it
    template_merge
    or
    /usr/local/bin/template_merge

NOTES:

  • Running template_merge without any arguments will produce a usage summary.
  • template_merge is written in Perl, so no compilation is needed.
  • On a Unix/Linux OS if your perl binary is not installed at /usr/bin/perl you may need to edit the first line of the script accordingly.
  • On a Microsoft OS you may need to put a .pl extension on template_merge so Windows will know to associate it with perl.
  • template_merge has not been fully tested on various platforms outside of linux.

Usage

Running template_merge by itself will give you the usage synopsis. It only requires one option, which is -t to specify a template. It is possible to have a template without the need for the -p option if it does not use the “parm” anchor. This is usualy not the case however.

Failures:

Each anchor should put some sort of UNKNOWN_XXXXX message in place of the anchor. You should be able to search through the output to determine what failed by searching for the key word “UNKNOWN”

Return codes can be tested via the shell variable $? and should be 0 on success or anything greater than 1 on failure. The return code should be a count of how many things failed.

Templates

A template is simply a text file containing the raw text with anchors to be replaced during a template_merge. Anchors are specific tags that are replaced with valid data based on the type of anchor used.

Details of each anchor:

$[parm:MY_PARAMETER]
    -- Uses the value of MY_PARMAMETER from the specified parm file

$[include:/tmp/file]
    -- Uses the contents of /tmp/file as additional template data
       If you use the -d option you can set a default directory for
       include files to be located.  This helps one not have to
       fully qualify the path to each file included.  Include paths
       can also be executables that output to STDOUT.  For example:
       $[include:/bin/extract_site_template my_template] could be a
       program that gets the template named my_template from a database
       table containing templates

$[env:HOSTNAME]
    -- Uses the value of the environment var $HOSTNAME

$[dns:www.google.com]
    -- Uses the first IP address returned by the gethostbyname function

$[cmd:who]
 or
$[cmdx:who]
    -- Uses the output of specified command with a trailing newline (cmd) or
       no trailing newline (cmdx).  When using cmd or cmdx commands all entries
       in any specified parm file will be placed into the environment with
       MERGE_ appended to them.  So a parm entry of SITE_NAME=my_cool_site
       becomes MERGE_SITE_NAME=my_cool_site in the environment. This allows
       one to utilize parm entries from within their command line tools.

$[if:{type}question:answer]
...
$[endif]
    -- Displays the contents between the if and endif statements when the
       condition matches.  The available types are parm, env, and dns.  The
       result of "{type}question" should match the "answer".  You can use the
       "notif" operator to negate the match.  For the parm and env types you
       can leave the "answer" blank to test for the simple existence of the
       "question".  You can also use simple regular expression matching in
       the "answer" field.

  Examples:
    $[if:{parm}SOME_NUM:1234] -- matches if the parm SOME_NUM was set to 1234
    $[if:{env}USER:mdp] -- matches if the environment var USER is set to mdp
    $[if:{dns}google.com:64.233.187.99] -- matches if google.com resolves to
    ip address 64.233.187.99. (Will match any, if multiple IPs are returned)
    $[notif:{parm}ABCD:1234] -- matches if the parm ABCD was NOT set to 1234
    $[if:{parm}ABCD:] -- matches if the parm ABCD exists, no matter its value
    $[if:{env}PATH:.*:/usr/bin:.*] -- Checks that /usr/bin/ is in the PATH

NOTE: When using cmd or cmdx commands all entries in any specified parm file will be placed into the environment with MERGE_ appended to them. So a parm entry of SITE_NAME=my_cool_site becomes MERGE_SITE_NAME=my_cool_site in the environment. This allows one to utilize parm entries from within their command line tools.

Parm Files

A parm file is simply a file containing key equals value pairs similar to an .INI file. A parm file is usually something that is generated from a database or is maintained manually in the context of a /etc/master.parm file. This could contain settings that are global to a particular system such as an enable password or dns server IP address.

Parm file format is a simple KEY=value. Each key name SHOULD be in uppercase. Key names MUST be one word. Parm values can be any string, with spaces. You can put comments in using the # character but they must be the first character of the line. You can use the standard include anchor to include other parm files into this parm. The include anchor can be a file or an executable that outputs parm file format to STDOUT. Include statements MUST be the first lines of the parm file to ensure the are read first. If you have multiple include file statements, they will be read in order listed in the parm file. This means that any included file could overwrite the value of a duplicate key listed in another included file specified previously. This is useful for including higher level global parm files.

An example:

$[include:/etc/master.parm]
$[include:cat /tmp/test.parm]
USER_NAME=Matt Pascoe
LOGIN=mdp
# Just a fake hire date
HIRE_DATE=1/1/20
HOST_IP=10.1.2.4

Misc Options

The -s option is for adding a “suffix” to the generated template. It can be used as a general signature or in the case of templating Cisco configurations you can put ”!\nend” to ensure that there is always an end statement on the config.

The -o option is used to output the generated results to the specified file.

The -v option will increase the debug output verbosity the more times it is used. -v for debug level 1 or -vvv for debug level 3.

The -d option sets the working directory so that include anchors dont have to have full file paths listed in them.

EXAMPLES:

There are some included test parm files and template files in the directory “examples”. To execute them simply run the following command while in that directory:

template_merge -t template.tmpl -p parm.parm

Running this should give you an example of that each option does. It shows both a successfull invocation as well as what happens when each anchor fails due to bad information or syntax.

Warnings/Known Bugs

  • You might see the following messages:
    Can't exec "template.tmpl": No such file or directory at ./template_merge line 749.
    Can't exec "parm.parm": No such file or directory at ./template_merge line 713.

This means that the files specified by -p or -t or that have been defined by $[include:blah] are not found or are not executable. Due to the use of backticks to execute files, I'm not able to test properly without forcing ALL executed commands to be fully qualified. I chose to just let things error out this way as it is sufficiently describing the problem.

  • Keep in mind that this program is issuing shell commands via cmdx or -p and -t options. Just be careful who you allow to run this program, and at what privilege. I don't know of any better ways to account for this securely without loosing functionality so I have no intention on changing this unless someone can convince me of a secure way to get the same job done.

Todo

Contributors

The team at my prior employer who helped come up with many ideas for this tool.

Brandon Zehm <http://caspian.dotconf.net> – Who I have patterned a lot of this code from.

Eric Woerner – Thanks for all the testing and code breaking.

Discussion

 
utils/template_merge.txt · Last modified: 2009/02/22 16:54 (external edit)