Package: pepa
PepaConfiguration templating for SaltStack using Hierarchical substitution and Jinja.Pepa is part of the SaltStack as of release 2014.7.Quick testingYou can easily test Pepa from the Command Line.Create a virtual env. and install the required modules.virtualenvvenvcdvenvsourcebin/activatepipinstallpepaClone and run Pepa.gitclonehttps://github.com/mickep76/pepa.gitcdpepapepa-cexamples/mastertest.example.com-dTest and validate templates.pepa-test--configexamples/master-dLook at output.pepa-test--configexamples/master-d-sInstall Pepagitclonehttps://github.com/mickep76/pepa.gitmkdir-p/srv/salt/ext/pillarcppillar/pepa.py/srv/salt/ext/pillar/pepa.pyConfiguring Pepaextension_modules:/srv/salt/extext_pillar:-pepa:resource:host# Name of resource directory and sub-key in pillarssequence:# Sequence used for hierarchical substitution-hostname:# Name of keyname:input# Alias used for template directorybase_only:True# Only use templates from Base environment, i.e. no staging-default:-environment:-location..region:name:region-location..country:name:country-location..datacenter:name:datacenter-roles:-osfinger:name:os-hostname:name:overridebase_only:Truesubkey:True# Create a sub-key in pillars, named after the resource in this case [host]subkey_only:True# Only create a sub-key, and leave the top level untouchedpepa_roots:# Base directory for each environmentbase:/srv/pepa/base# Path for base environmentdev:/srv/pepa/base# Associate dev with baseqa:/srv/pepa/qaprod:/srv/pepa/prod# Use a different delimiter for nested dictionaries, defaults to '..' since some keys may use '.' in the name#pepa_delimiter: ..# Supply Grains for Pepa, this should **ONLY** be used for testing or validation#pepa_grains:#  environment: dev# Supply Pillar for Pepa, this should **ONLY** be used for testing or validation#pepa_pillars:#  saltversion: 0.17.4# Enable debug for Pepa, and keep Salt on warning#log_level: debug#log_granular_levels:#  salt: warning#  salt.loaded.ext.pillar.pepa: debugPepa can also be used in Master-less SaltStack setup.Command lineusage:pepa[-h][-cCONFIG][-d][-gGRAINS][-pPILLAR][-n][-v]hostnamepositionalarguments:hostnameHostnameoptionalarguments:-h,--helpshowthishelpmessageandexit-cCONFIG,--configCONFIGConfigurationfile-rRESOURCE,--resourceRESOURCEResource,defaultstofirstresource-d,--debugPrintdebuginfo-gGRAINS,--grainsGRAINSInputGrainsasYAML-pPILLAR,--pillarPILLARInputPillarasYAML-n,--no-colorNocoloroutput-v,--validateValidateoutputTemplatesTemplates is configuration for a host or software, that can use information from Grains or Pillars. These can then be used for hierarchically substitution.Example File:host/input/test_example_com.yamllocation..region:emealocation..country:nllocation..datacenter:foobarenvironment:devroles:-salt.masternetwork..gateway:10.0.0.254network..interfaces..eth0..hwaddr:00:20:26:a1:12:12network..interfaces..eth0..dhcp:Falsenetwork..interfaces..eth0..ipv4:10.0.0.3network..interfaces..eth0..netmask:255.255.255.0network..interfaces..eth0..fqdn:{{hostname}}cobbler..profile:fedora-19-x86_64As you see in this example you can use Jinja directly inside the template.Example File:host/region/amer.yamlnetwork..dns..servers:-10.0.0.1-10.0.0.2time..ntp..servers:-ntp1.amer.example.com-ntp2.amer.example.com-ntp3.amer.example.comtime..timezone:America/Chihuahuayum..mirror:yum.amer.example.comEach template is named after the value of the key using lowercase and all extended characters are replaced with underscore.Example:osfinger: Fedora-19Would become:fedora_19.yamlNested dictionariesIn order to create nested dictionaries as output you can use double dot“..”as a delimiter. You can change this using “pepa_delimiter” we choose double dot since single dot is already used by key names in some modules, and using “:” requires quoting in the YAML.Example:network..dns..servers:-10.0.0.1-10.0.0.2network..dns..options:-timeout:2-attempts:1-ndots:1network..dns..search:-example.comWould become:network:dns:servers:-10.0.0.1-10.0.0.2options:-timeout:2-attempts:1-ndots:1search:-example.comOperatorsOperators can be used to merge/unset a list/hash or set the key as immutable, so it can’t be changed.OperatorDescriptionmerge()Merge list or hashunset()Unset keyimmutable()Set the key as immutable, so it can’t be changedimerge()Set immutable and mergeiunset()Set immutable and unsetExample:network..dns..search..merge():-foobar.com-dummy.nlowner..immutable():Operationshost..printers..unset():TestingPepa also come’s with a test/validation tool for templates. This allows you to test for valid Jinja/YAML and validate key values.Command Lineusage:pepa-test[-h][-cCONFIG][-rRESOURCE][-d][-s][-t][-n]optionalarguments:-h,--helpshowthishelpmessageandexit-cCONFIG,--configCONFIGConfigurationfile-rRESOURCE,--resourceRESOURCEConfigurationfile,defaultstofirstresource-d,--debugPrintdebuginfo-s,--showShowresultoftemplate-t,--teamcityOutputvalidationinTeamCityformat-n,--no-colorNocoloroutputTestA test is a set of input values for a template, it’s generally a good idea to create a separate test for each outcome if you have Jinja if statements.Example:host/default/tests/default-1.yamlgrains..osfinger:Fedora-20location..region:emeaYou can also use Jinja inside a test, for example if you wan’t to iterate through test values.SchemaA schema is a set of validation rules for each key/value. Schemas useCerberusmodule for validation.Example:host/schemas/pkgrepo.yaml{%set hostname = '^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-zA-Z]{2,6}$' %}{%set url = '(http|https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?)' %}pkgrepo..mirror:type:stringregex:{{hostname}}pkgrepo..type:type:stringallowed:yumpkgrepo..osabbr:type:stringregex:^(fc|rhel)[0-9]+${%for repo in['base','everything','updates']%}pkgrepo..repos..{{ repo }}..name:type:stringregex:^[A-Za-z\ 0-9\-\_]+$pkgrepo..repos..{{ repo }}..baseurl:type:stringregex:{{url}}{%endfor %}You can also use Jinja inside a schema, for example if you wan’t to iterate through a list of different keys.You can create complicated datastructures underneth a key, but it’s advisable to split it in several
keys using the delimiter for a nested data structures.Badnetwork:interfaces:eth0:ipv4:192.168.1.2netmask:255.255.255.0Goodnetwork..interfaces..eth0..ipv4:192.168.1.2network..interfaces..eth0..netmask:255.255.255.0The first example you can’t properly use substitution and defining the schema becomes more complicated.