Search code examples
debuggingreverse-engineeringsalt-stackconfiguration-management

SaltStack: Reverse engineering where a file comes from


If you look at a host which was set up be SaltStack, then it is sometimes like looking at a binary file with vi.

You have no clue how the config/file was created.

This makes trouble shooting errors hard. Reverse engineering where a file comes from takes too much time.

My goal: Make it easy to find the way from looking at the unix config file on the minion (created by salt) to the source where this configuration came from. Like $Id$ in svn and cvs.

One idea a friend and I had:

The state file.managed should (optionally) add the source of the file.

Example:

My sls file contains this:

file_foo_bar:
  file.managed:
    - source:
      - salt://foo/bar

Then the created file should contain this comment.

# Source: salt://foo/bar

Of course this is not simple, since there are different ways to put comments into configuration files.

Is this feasible? Or is there a better solution to my goal.

Update

Usually I know what I did wrong and can find the root easily. The problem arises if several people work on a state tree.


Solution

  • This is a starting point where you can get the date and time of the modified file when its managed by Salt by using Salt Pillar.

    Lets call our variable salt_managed. Create a pillar file like the following:

    {% set managed_text = 'Salt managed: File modified on ' + salt.cmd.run('date "+%Y-%m-%d %H:%M:%S"') %}
    
    salt_managed: {{ managed_text | yaml_dquote }}
    

    Then on the minion when you call the pillar you will get the following result:

    $ salt-call pillar.get salt_managed
    local:
        Salt managed: File modified on 2016-10-18 11:12:40
    

    And you can use this by adding it on the top of your config files for example like this:

    {{ pillar.get('salt_managed') }}
    

    Update:

    I found a work around that might be useful for someone. Lets say we have a multiple states that could modify the same file. How can we know that State X is the responsible for modifying that file ? by doing the following steps:

    1- I have created a state like this one:

    Create a File:
      file.managed:
        - name: /path/to/foofile
        - source: salt://statedir/barfile
    Add file header:
      file.prepend:
        - name: /path/to/foofile
        - text: "This file was managed by using this salt state {{ sls }}"
    

    The contents of barfile is:

    This is a new file
    

    2- Call the state from the minion and this will be the result:

    $ salt-call state.sls statedir.test
    local:
    ----------
              ID: Create a File
        Function: file.managed
            Name: /path/to/foofile
          Result: True
         Comment: File /path/to/foofile updated
         Started: 07:50:45.254994
        Duration: 1034.585 ms
         Changes:   
                  ----------
                  diff:
                      New file
                  mode:
                      0644
    ----------
              ID: Add file header
        Function: file.prepend
            Name: /path/to/foofile
          Result: True
         Comment: Prepended 1 lines
         Started: 07:50:46.289766
        Duration: 3.69 ms
         Changes:   
                  ----------
                  diff:
                      ---  
                      +++  
                      @@ -1,1 +1,2 @@
                      +This file was managed by using this salt state statedir.test
                       This is a new file
    
    Summary for local
    ------------
    Succeeded: 2 (changed=2)
    Failed:    0
    ------------
    Total states run:     2
    

    Currently the content of foofile is:

    This file was managed by using this salt state statedir.test
    This is a new file