Salt States can aggressively manipulate files on a system. There are a number of ways in which files can be managed.
Regular files can be enforced with the managed function. This function downloads files from the salt master and places them on the target system. The downloaded files can be rendered as a jinja, mako, or wempy template, adding a dynamic component to file management. An example of file.managed which makes use of the jinja templating system would look like this:
/etc/http/conf/http.conf:
file.managed:
- source: salt://apache/http.conf
- user: root
- group: root
- mode: 644
- template: jinja
- context:
custom_var: "override"
- defaults:
custom_var: "default value"
other_var: 123
The source parameter can be specified as a list. If this is done, then the first file to be matched will be the one that is used. This allows you to have a default file on which to fall back if the desired file does not exist on the salt fileserver. Here's an example:
/etc/foo.conf
file.managed:
- source:
- salt://foo.conf.{{ grains['fqdn'] }}
- salt://foo.conf.fallback
- user: foo
- group: users
- mode: 644
Directories can be managed via the directory function. This function can create and enforce the permissions on a directory. A directory statement will look like this:
/srv/stuff/substuf:
file.directory:
- user: fred
- group: users
- mode: 755
- makedirs: True
If you need to enforce user and/or group ownership or permissions recursively on the directory's contents, you can do so by adding a recurse directive:
/srv/stuff/substuf:
file.directory:
- user: fred
- group: users
- mode: 755
- makedirs: True
- recurse:
- user
- group
- mode
As a default, mode will resolve to dir_mode and file_mode, to specify both directory and file permissions, use this form:
/srv/stuff/substuf:
file.directory:
- user: fred
- group: users
- file_mode: 744
- dir_mode: 755
- makedirs: True
- recurse:
- user
- group
- mode
Symlinks can be easily created; the symlink function is very simple and only takes a few arguments:
/etc/grub.conf:
file.symlink:
- target: /boot/grub/grub.conf
Recursive directory management can also be set via the recurse function. Recursive directory management allows for a directory on the salt master to be recursively copied down to the minion. This is a great tool for deploying large code and configuration systems. A state using recurse would look something like this:
/opt/code/flask:
file.recurse:
- source: salt://code/flask
- include_empty: True
Verify that the named file or directory is absent, this will work to reverse any of the functions in the file state module.
Prepare accumulator which can be used in template in file.managed state. accumulator dictionary becomes available in template.
Ensure that some text appears at the end of a file
The text will not be appended again if it already exists in the file. You may specify a single line of text or a list of lines to append.
Multi-line example:
/etc/motd:
file.append:
- text: |
Thou hadst better eat salt with the Philosophers of Greece,
than sugar with the Courtiers of Italy.
- Benjamin Franklin
Multiple lines of text:
/etc/motd:
file.append:
- text:
- Trust no one unless you have eaten much salt with him.
- Salt is born of the purest of parents: the sun and the sea.
New in version 0.9.5.
Comment out specified lines in a file.
The file will be backed up before edit with this file extension
Warning
This backup will be overwritten each time sed / comment / uncomment is called. Meaning the backup will only be useful after the first invocation.
Usage:
/etc/fstab:
file.comment:
- regex: ^bind 127.0.0.1
New in version 0.9.5.
Ensure that a named directory is present and has the right perms
Enforce user/group ownership and mode of directory recursively. Accepts a list of strings representing what you would like to recurse. Example:
/var/log/httpd:
file.directory:
- user: root
- group: root
- dir_mode: 755
- file_mode: 644
- recurse:
- user
- group
- mode
Verify that the named file or directory is present or exists. Ensures pre-requisites outside of Salt's purview (e.g., keytabs, private keys, etc.) have been previously satisfied before deployment.
Manage a given file, this function allows for a file to be downloaded from the salt master and potentially run through a templating system.
The source file to download to the minion, this source file can be hosted on either the salt master server, or on an HTTP or FTP server. For files hosted on the salt file server, if the file is located on the master in the directory named spam, and is called eggs, the source string is salt://spam/eggs. If source is left blank or None, the file will be created as an empty file and the content will not be managed
If the file is hosted on a HTTP or FTP server then the source_hash argument is also required
This can be either a file which contains a source hash string for the source, or a source hash string. The source hash string is the hash algorithm followed by the hash of the file: md5=e138491e9d5b97023cea823fe17bac22
The file can contain checksums for several files, in this case every line must consist of full name of the file and checksum separated by space:
Example:
/etc/rc.conf md5=ef6e82e4006dee563d98ada2a2a80a27
/etc/resolv.conf sha256=c8525aee419eb649f0233be91c151178b30f0dff8ebbdcc8de71b1d5c8bcc06a
Apply a patch to a file. Note: a suitable patch executable must be available on the minion when using this state function.
Usage:
# Equivalent to ``patch --forward /opt/file.txt file.patch``
/opt/file.txt:
file.patch:
- source: salt://file.patch
- hash: md5=e138491e9d5b97023cea823fe17bac22
Recurse through a subdirectory on the master and copy said subdirectory over to the specified path.
When copying, include only this pattern from the source. Default is glob match; if prefixed with 'E@', then regexp match. Example:
- include_pat: hello* :: glob matches 'hello01', 'hello02'
... but not 'otherhello'
- include_pat: E@hello :: regexp matches 'otherhello',
'hello01' ...
When copying, exclude this pattern from the source. If both include_pat and exclude_pat are supplied, then it will apply conditions cumulatively. i.e. first select based on include_pat, and then within that result apply exclude_pat.
Also, when 'clean=True', exclude this pattern from the removal list and preserve in the destination. Example:
- exclude: APPDATA* :: glob matches APPDATA.01,
APPDATA.02,.. for exclusion
- exclude: E@(APPDATA)|(TEMPDATA) :: regexp matches APPDATA
or TEMPDATA for exclusion
When copying, only copy paths which are depth maxdepth from the source path. Example:
- maxdepth: 0 :: Only include files located in the source
directory
- maxdepth: 1 :: Only include files located in the source
or immediate subdirectories
If the source file exists on the system, rename it to the named file. The named file will not be overwritten if it already exists unless the force option is set to True.
Maintain a simple edit to a file
The file will be searched for the before pattern before making the edit. In general the limit pattern should be as specific as possible and before and after should contain the minimal text to be changed.
Usage:
# Disable the epel repo by default
/etc/yum.repos.d/epel.repo:
file.sed:
- before: 1
- after: 0
- limit: ^enabled=
# Remove ldap from nsswitch
/etc/nsswitch.conf:
file.sed:
- before: 'ldap'
- after: ''
- limit: '^passwd:'
New in version 0.9.5.
Create a symlink
Replicate the 'nix "touch" command to create a new empty file or update the atime and mtime of an existing file.
Usage:
/var/log/httpd/logrotate.empty:
file.touch
New in version 0.9.5.
Uncomment specified commented lines in a file
Usage:
/etc/adduser.conf:
file.uncomment:
- regex: EXTRA_GROUPS
New in version 0.9.5.