Search code examples
salt-project

How do I implement a 'pillar.example' from a SaltStack Formula?


If this explanation exists somewhere, I've spent 3 months trying to find it, and failed. I come from a Puppet background, however for various reasons I really want to try replacing it with Salt.

I've gotten a basic setup and I can code my own states and see them work without any issues. The documentation on this is pretty clear. Where I'm stuck is attempting to implement a community salt formula. I can include the formula with it's basic setup and they work fine, however I cannot figure out how to override the defaults from my pillar data. This seems to be where the Salt documentation is weakest.

The documentation states that you should check the pillar.example for how to configure the formula. The pillar.example gives the configuration part clearly, however nether the documentation or the pillar.example tell you how to include this into your pillar data.

In my case I'm trying to use the snmp-formula. I've got a basic setup for my salt file structure, which you can see from my file roots:

file_roots:
  base:
  - /srv/salt/base
  - /srv/formulas/snmp-formula

Inside base I have two pillars:

base/
  top.sls
  common.sls

top.sls is very simple:

base:
  '*':
    - common

common.sls has all common config:

include:
  - snmp
  - snmp.conf
  - snmp.trap
  - snmp.conftrap

tcpdump:
  pkg.latest:
    - name: tcpdump

telnet:
  pkg.latest:
    - name: telnet

htop:
  pkg.latest:
    - name: htop

snmp:
  conf:
    location: 'Office'
    syscontact: 'Example.com Admin <admin@example.com>'
    logconnects: false
    # vacm com2sec's (map communities into security names)
    com2sec:
      - name: mynetwork
        source: 192.168.0.13/31
        community: public
    # vacm group's (map security names to group names)
    groups:
      - name: MyROGroup
        version: v1
        secname: mynetwork
      - name: MyROGroup
        version: v1c
        secname: mynetwork
    # vacm views (map mib trees to views)
    views:
     - name: all
        type: included
        oid: '.1'
    # vacm access (map groups to views with access restrictions)
    access:
      - name: MyROGroup
        context: '""'
        match: any
        level: noauth
        prefix: exact
        read: all
        write: none
        notify: none
    # v3 users for read-write
    rwusers:
      - username: 'nagios'
        passphrase: 'myv3password'
        view: all

In common.sls I've included the snmp-formula and then followed the pillar.example from the formula to customize the configuration. However when I run a test with this I get the following error:

Data failed to compile:
----------
    Detected conflicting IDs, SLS IDs need to be globally unique.
    The conflicting ID is 'snmp' and is found in SLS 'base:common' and SLS 'base:snmp'

I'm not sure how to proceed with this. It seems like I would have to actually modify the community formula directly to achieve what I want, which seems like the wrong idea. I want to be able to keep the community formula up to date with it's repository and coming from the Puppet perspective, I should be overriding a modules defaults as I need, not modifying the modules directly.

Can someone please make the missing connection for me? How do I implement the pillar.example?

The Salt formula in question is here:

https://github.com/saltstack-formulas/snmp-formula


Solution

  • I have finally figured this out, and it was a problem with a fundamental misunderstanding of the differences between 'file_roots' and 'pillar_roots' as well as 'pillars' vs 'states'. I don't feel that the documentation is very clear in the Getting Started guide about these so I'll explain it, but first the answer.

    ANSWER:

    To implement the above pillar.example, simply create a dedicated snmp.sls file in your 'base' environment in your pillar data:

    /srv/pillar/snmp.sls:

    snmp:
      conf:
        location: 'Office'
        syscontact: 'Example.com Admin <admin@example.com>'
        logconnects: false
        # vacm com2sec's (map communities into security names)
        com2sec:
          - name: mynetwork
            source: 192.168.0.13/31
            community: public
        # vacm group's (map security names to group names)
        groups:
          - name: MyROGroup
            version: v1
            secname: mynetwork
          - name: MyROGroup
            version: v1c
            secname: mynetwork
        # vacm views (map mib trees to views)
        views:
         - name: all
            type: included
            oid: '.1'
            mask: 80
        # vacm access (map groups to views with access restrictions)
        access:
          - name: MyROGroup
            context: '""'
            match: any
            level: noauth
            prefix: exact
            read: all
            write: none
            notify: none
        # v3 users for read-write
        rwusers:
          - username: 'nagios'
            passphrase: 'myv3password'
            view: all
    

    Your pillar_root must also include a top.sls (not to be confused with the top.sls in your file_roots for your states) like this:

    /srv/pillar/top.sls

    base:
      '*':
        - snmp
    

    IMPORTANT: This directory and this top.sls for pillar data cannot exist or be included by your file_roots! This is where I was going wrong. For a complete picture, this is the the config I now have:

    /etc/salt/master: (snippet)

    file_roots:
      base:
      - /srv/salt/base
      - /srv/formulas/snmp-formula
    
    pillar_roots:
      base:
      - /srv/pillar
    

    Inside /srv/salt/base I have a top.sls which includes a common.sls for the 'base' environment. This is where the snmp-formula and it's states are included.

    /srv/salt/base/top.sls:

    base/
      top.sls
      common.sls
    

    /srv/salt/base/common.sls:

    include:
      - snmp
      - snmp.conf
      - snmp.trap
      - snmp.conftrap
    
    tcpdump:
      pkg.latest:
        - name: tcpdump
    
    telnet:
      pkg.latest:
        - name: telnet
    
    htop:
      pkg.latest:
        - name: htop
    

    Now the snmp parameter in the pillar data does not conflict with ID of the snmp state from the formula included by the state data.