How to Clear Directory Contents Using SaltStack State Files (Removing *.conf Files Example)


2 views

When managing services with SaltStack, we often need to ensure clean environments before deploying new configurations. A common scenario is removing old configuration files (like *.conf in /etc/supervisord/conf.d/) before setting up new supervisor services.

The attempted solution using file.absent doesn't work because:

/etc/supervisor/conf.d/*:
  file.absent

This fails because file.absent operates on complete paths, not patterns. SaltStack doesn't expand glob patterns in this context.

Method 1: Using file.directory with clean=True

The proper way to clear a directory while keeping the directory itself:

clear_supervisor_configs:
  file.directory:
    - name: /etc/supervisord/conf.d/
    - clean: True
    - require_in:
      - file: /etc/supervisord/conf.d/new_service.conf

Method 2: Pattern-based Removal with cmd.run

For more control over which files to remove:

remove_old_configs:
  cmd.run:
    - name: rm -f /etc/supervisord/conf.d/*.conf
    - onlyif: test -n "$(ls /etc/supervisord/conf.d/*.conf 2>/dev/null)"

Method 3: Advanced Globbing with file.absent

SaltStack's more recent versions support this pattern:

{% for file in salt['file.find']('/etc/supervisord/conf.d', name='*.conf') %}
remove_{{ file|replace('/', '_') }}:
  file.absent:
    - name: {{ file }}
{% endfor %}

When clearing directories in SaltStack:

  • Always test with salt-call state.apply test=True first
  • Consider adding - require or - require_in to ensure proper ordering
  • For production systems, implement a backup mechanism

Here's a complete solution with safety checks:

backup_old_configs:
  cmd.run:
    - name: |
        mkdir -p /var/backups/supervisor/$(date +%Y%m%d)
        cp /etc/supervisord/conf.d/*.conf /var/backups/supervisor/$(date +%Y%m%d)/
    - onlyif: test -n "$(ls /etc/supervisord/conf.d/*.conf 2>/dev/null)"

clear_config_directory:
  file.directory:
    - name: /etc/supervisord/conf.d/
    - clean: True
    - require:
      - cmd: backup_old_configs

deploy_new_configs:
  file.managed:
    - name: /etc/supervisord/conf.d/new_service.conf
    - source: salt://supervisor/files/new_service.conf
    - require:
      - file: clear_config_directory

When trying to clear configuration files before deployment, many SaltStack users first attempt the file.absent state. However, this approach has limitations when dealing with wildcard patterns:

/etc/supervisor/conf.d/*.conf:
  file.absent

This state declaration won't work because file.absent expects explicit paths, not glob patterns. The state simply checks if the literal path "/etc/supervisor/conf.d/*.conf" exists as a file (which it doesn't) and does nothing.

Solution 1: Using cmd.run with find

For a reliable cleanup operation before deploying new configurations:

clean_supervisor_configs:
  cmd.run:
    - name: find /etc/supervisor/conf.d/ -name "*.conf" -delete
    - onlyif: test -d /etc/supervisor/conf.d/

The onlyif clause ensures the command only runs if the directory exists, preventing errors.

Solution 2: SaltStack file.glob_remove

A more Salt-native approach using the file.glob_remove execution module:

remove_old_configs:
  module.run:
    - name: file.glob_remove
    - path: /etc/supervisor/conf.d/*.conf

Solution 3: Combining with requisites

When this cleanup needs to happen before other states:

clean_configs:
  module.run:
    - name: file.glob_remove
    - path: /etc/supervisor/conf.d/*.conf

deploy_new_configs:
  file.managed:
    - name: /etc/supervisor/conf.d/myapp.conf
    - source: salt://supervisor/files/myapp.conf
    - require:
      - clean_configs

For more complex scenarios where you need to:

  • Preserve certain files while deleting others
  • Handle permission issues
  • Log deleted files

Consider this enhanced version:

selective_cleanup:
  module.run:
    - name: file.find
    - path: /etc/supervisor/conf.d/
    - name: '*.conf'
    - notname: 'keep_me.conf'
    - delete: True
    - print: name