Answers: <p>Yes - there are at least two options available for managing files in the manner you describe. The first such way is to manage the entire directory using <a href="https://docs.saltstack.com/en/latest/ref/states/all/salt.states.file.html#salt.states.file.directory" rel="nofollow noreferrer">file.directory</a>:</p>
  
  <pre><code>/opt/apiv2:
    file.directory:
      - user: root
      - group: root
      - dir_mode: 755
      - file_mode: 644
      - recurse:
        - user
        - group
        - mode
  </code></pre>
  
  <p>The second way can manage a manifest of several files at many paths is to use the <code>source_hash</code> feature of <a href="https://docs.saltstack.com/en/latest/ref/states/all/salt.states.file.html#salt.states.file.managed" rel="nofollow noreferrer">file.managed</a>:</p>
  
  <p>This allows you to provide a source tar file and a file containing md5sum hashes:</p>
  
  <pre><code>apiv2-0.7.3.tar.gz:
    file.managed:
      - name: /tmp/apiv2-0.7.3.tar.gz
      - source: salt:///apiv2/distrib/apiv2-0.7.3.tar.gz
      - source_hash: salt:///apiv2/distrib/manifest-0.7.3.hash
  </code></pre>
  
  <p>You would then create a text file on your salt server /srv/salt/apiv2/distrib/manifest-0.7.3.hash with contents similar to:</p>
  
  <pre><code>37b51d194a7513e45b56f6524f2d51f2    /opt/apiv2/apiv2.properties
  acbd18db4cc2f85cedef654fccc4a4d8    /opt/apiv2/repo/bootstrap.jar
  73feffa4b7f6bb68e44cf984c85f6e88    /opt/apiv1/apiv1.properties
  </code></pre>
  
  <p>Your <em>might</em> even be able to use templating,</p>
  
  <pre><code>apiv2-0.7.3.tar.gz:
    file.managed:
      - name: /tmp/apiv2-0.7.3.tar.gz
      - source: salt:///apiv2/distrib/apiv2-0.7.3.tar.gz
      - source_hash: salt:///apiv2/distrib/manifest-0.7.3.hash
      - template: jinja
  </code></pre>
  
  <p>however Salt Stack might want to push down the file each time because after the templates are rendered, the hash will have changed, so the creators might just have elected to throw an error if you try these two features together. In short, Your Mileage May Vary<sup>TM</sup></p>
  
Answers: CC BY-SA 3.0
Answers: 2017-08-15T18:25:32.487Z
Answers: My fault. I needed to update the extension when I was writing my example. It's just an uncompressed text file.
Answers: James Shewey
Answers: CC BY-SA 3.0
Answers: 2017-08-16T06:53:29.863Z
Answers: Hi @JamesShewey, thanks for your answer, I'll look in to these methods later today and let you know how I get on - Also, I should've mentioned in my question (I'll edit now); is my current method considered bad practice? Or is it just an inefficient/ugly way of doing it?
Answers: jto
Answers: CC BY-SA 3.0
Answers: 2017-08-16T06:55:28.867Z
Answers: @JamesShewey Also, with the first method you highlighted, will it accurately identify individual files within the directory?
Answers: jto
Answers: CC BY-SA 3.0
Answers: 2017-08-16T14:53:41.617Z
Answers: It will *accurately identify* them but it's not really *individual* - you are pushing down an entire directory.
Answers: James Shewey
Answers: CC BY-SA 3.0
Answers: 2017-08-15T15:43:03.597Z
Answers: 2017-08-15T20:30:28.353Z
Answers: 2017-08-15T20:30:28.353Z
Answers: James Shewey
Body: <p>I asked a question recently regarding the most efficient and scalable way to check which files/services exist in multiple environments. Thanks to an answer I have successfully set up roles for all of my salt minions.</p>
  
  <p>I am now in the process of writing my first salt state which will check that all expected files/services are present for all minions with the <code>apiserver</code> role. </p>
  
  <p>I am using the <code>file.exists</code> feature, however as you can expect there are 100's of files/services I wish to check, I'm sure there must be a way of listing these files/services in a list or string? I can't find anything in the documentation under file.exists but it is possible in other file.'s</p>
  
  <p>Here is the current state of my <code>init.sls</code> file:</p>
  
  <pre><code># This state will check all minions identified as 'apiserver' for files and/or services which should exist
  
  # This section checks the 'checkservices.sh' is present in /opt (used for Jenkins check jobs)
  
  checkservices.sh:
    file.exists:
      - name: /opt/checkservices.sh
  
  # This section checks for expected files/scripts within /opt/apiv2/
  
  apiv2.properties:
    file.exists:
      - name: /opt/apiv2/apiv2.properties
  
  jvm.options:
    file.exists:
      - name: /opt/apiv2/jvm.options
  
  restart.sh:
    file.exists:
      - name: /opt/apiv2/restart.sh
  
  status.sh:
    file.exists:
      - name: /opt/apiv2/status.sh
  
  shutdown.sh:
    file.exists:
      - name: /opt/apiv2/shutdown.sh
  
  start.sh:
    file.exists:
      - name: /opt/apiv2/start.sh
  
  # This section checks for 'bootstrap.jar' in /opt/apiv2/repo/
  
  bootstrap.jar:
    file.exists:
      - name: /opt/apiv2/repo/bootstrap.jar
  </code></pre>
  
  <p>My second question is; is my current method (above) considered bad practice or is it just an ugly/inefficient way of doing it?</p>
  
Tags: <configuration-management><salt><yaml>
Title: Is it possible to use a list with 'file.exists' in Salt?
UserDisplayName: jto
ThreadText: # Is it possible to use a list with 'file.exists' in Salt?
  
  (Asked by: username_0 on 2017-08-15)
  
  I asked a question recently regarding the most efficient and scalable way to check which files/services exist in multiple environments. Thanks to an answer I have successfully set up roles for all of my salt minions.
  
  I am now in the process of writing my first salt state which will check that all expected files/services are present for all minions with the `apiserver` role.
  
  I am using the `file.exists` feature, however as you can expect there are 100's of files/services I wish to check, I'm sure there must be a way of listing these files/services in a list or string? I can't find anything in the documentation under file.exists but it is possible in other file.'s
  
  Here is the current state of my `init.sls` file:
  
  ```
  # This state will check all minions identified as 'apiserver' for files and/or services which should exist
  
  # This section checks the 'checkservices.sh' is present in /opt (used for Jenkins check jobs)
  
  checkservices.sh:
    file.exists:
      - name: /opt/checkservices.sh
  
  # This section checks for expected files/scripts within /opt/apiv2/
  
  apiv2.properties:
    file.exists:
      - name: /opt/apiv2/apiv2.properties
  
  jvm.options:
    file.exists:
      - name: /opt/apiv2/jvm.options
  
  restart.sh:
    file.exists:
      - name: /opt/apiv2/restart.sh
  
  status.sh:
    file.exists:
      - name: /opt/apiv2/status.sh
  
  shutdown.sh:
    file.exists:
      - name: /opt/apiv2/shutdown.sh
  
  start.sh:
    file.exists:
      - name: /opt/apiv2/start.sh
  
  # This section checks for 'bootstrap.jar' in /opt/apiv2/repo/
  
  bootstrap.jar:
    file.exists:
      - name: /opt/apiv2/repo/bootstrap.jar
  
  ```
  
  My second question is; is my current method (above) considered bad practice or is it just an ugly/inefficient way of doing it?
  
  **Tags:** configuration-management, salt, yaml
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2017-08-15. Score: 1 | Accepted answer
  
  Yes - there are at least two options available for managing files in the manner you describe. The first such way is to manage the entire directory using [file.directory](https://docs.saltstack.com/en/latest/ref/states/all/salt.states.file.html#salt.states.file.directory):
  
  ```
  /opt/apiv2:
    file.directory:
      - user: root
      - group: root
      - dir_mode: 755
      - file_mode: 644
      - recurse:
        - user
        - group
        - mode
  
  ```
  
  The second way can manage a manifest of several files at many paths is to use the `source_hash` feature of [file.managed](https://docs.saltstack.com/en/latest/ref/states/all/salt.states.file.html#salt.states.file.managed):
  
  This allows you to provide a source tar file and a file containing md5sum hashes:
  
  ```
  apiv2-0.7.3.tar.gz:
    file.managed:
      - name: /tmp/apiv2-0.7.3.tar.gz
      - source: salt:///apiv2/distrib/apiv2-0.7.3.tar.gz
      - source_hash: salt:///apiv2/distrib/manifest-0.7.3.hash
  
  ```
  
  You would then create a text file on your salt server /srv/salt/apiv2/distrib/manifest-0.7.3.hash with contents similar to:
  
  ```
  37b51d194a7513e45b56f6524f2d51f2    /opt/apiv2/apiv2.properties
  acbd18db4cc2f85cedef654fccc4a4d8    /opt/apiv2/repo/bootstrap.jar
  73feffa4b7f6bb68e44cf984c85f6e88    /opt/apiv1/apiv1.properties
  
  ```
  
  Your *might* even be able to use templating,
  
  ```
  apiv2-0.7.3.tar.gz:
    file.managed:
      - name: /tmp/apiv2-0.7.3.tar.gz
      - source: salt:///apiv2/distrib/apiv2-0.7.3.tar.gz
      - source_hash: salt:///apiv2/distrib/manifest-0.7.3.hash
      - template: jinja
  
  ```
  
  however Salt Stack might want to push down the file each time because after the templates are rendered, the hash will have changed, so the creators might just have elected to throw an error if you try these two features together. In short, Your Mileage May VaryTM
  
  > **Comments:**
  > **username_1**: My fault. I needed to update the extension when I was writing my example. It's just an uncompressed text file.  
  > **username_0**: Hi @username_1, thanks for your answer, I'll look in to these methods later today and let you know how I get on - Also, I should've mentioned in my question (I'll edit now); is my current method considered bad practice? Or is it just an inefficient/ugly way of doing it?  
  > **username_0**: @username_1 Also, with the first method you highlighted, will it accurately identify individual files within the directory?  
  > **username_1**: It will *accurately identify* them but it's not really *individual* - you are pushing down an entire directory.  
  
  ---
  
  