check if file exists in salt file system salt:// - salt-stack

I would like to check if a file exist in salt file system (salt://) and add an instruction depending on that.
I precise that I use gitfs as a mount point in the salt file system and don't use /srv directory.
So more concretely I want to do something like that :
{% if salt['file.directory_exists']('salt://a_directory') %}
file.recurse:
- name: dest
- source: salt://a_directory
- template: jinja
{% endif %}
but it seem not to work.

I wanted to load yaml-files with package-lists for pkg.installed, but only if the yaml is on the master (file names are constructed by variables).
I'm using salt.modules.cp.list_master:
# Search path on the master:
{% set found = salt.cp.list_master(prefix='my/path/example.yaml') | count %}
{% if found %}
{# Do something… #}
{% endif %}
If you want to check a Directory, you can use this:
{% set found = salt.cp.list_master_dirs(prefix='my/path') | count %}

after seeing Mayr's answer, I did this:
{%- if not salt.cp.list_master(saltenv=saltenv, prefix='some/path/' ~ some_version ~ '/server.conf') | count %}
config_not_found_failure:
test.fail_without_changes:
- name: "some/path/{{some_version}}/server.conf not found in salt"
- failhard: True
{%- endif %}

Related

Experiencing issues with custom mine_functions in saltstack

I want to add a mine function that gets the hostname of a minion.
pillar/custom.sls
mine_functions:
custom:
- mine_function: grains.get
- nodename
I manually refresh the pillar data by running a
salt '*' saltutil.refresh_pillar
and when running salt '*' mine.get '*' custom the output is as expected, showing a list of minions all with the nodename data underneath.
The issue is when I try to do thew following in a template file:
{%- set custom_nodes = [] %}
bootstrap.servers={% for host, custom in salt['mine.get']('role:foo', 'custom', expr_form='grain').items() %}
{% do hosts.append(custom + ':2181') %}
{% endfor %}{{ custom_nodes|join(',') }}
I just get an empty space where my list of server nodenames should be.
I was hoping someone might be able to point out where I'm going wrong with this?
It looks like you are appending the list to hosts but then using custom_nodes with the join?
Was this on purpose?
I think what you actually want is
{%- set custom_nodes = [] %}
bootstrap.servers={% for host, custom in salt['mine.get']('role:foo', 'custom', expr_form='grain').items() %}
{% do custom_nodes.append(custom + ':2181') %}
{% endfor %}{{ custom_nodes|join(',') }}
This works fine for me:
pillar/custom.sls
mine_functions:
id_list:
mine_function: grains.get
key : nodename
templete.sls
{% for server in salt['mine.get']('*', 'id_list') | dictsort() %}
server {{ server }} {{ addrs[0] }}:80 check
{% endfor %}
Actually the answer was quite simple. I was unaware one needed to restart existing minions before they could access the mine data.

salt file.directoy_exists check in a loop

Trying to loop over a list of folder to check if the directory exists and then to clean that directory (remove all files).
{% set FOLDERS_TO_CLEAN = ['C:\Test\Folder1'] %}
{% for FOLDER in FOLDERS_TO_CLEAN %}
{% if salt['file.directory_exists']({{ FOLDER }}) %}
{{ FOLDER }}_delete:
file.directory:
- name: {{ FOLDER }}
- clean: True
- failhard: True
{% endif %}
{% endfor %}
The problematic line is the third line. With the variable FOLDER that ends up in a syntax error but when i change that to my test string it works. Any idea what i can change so that it works?
You need to have single quotes around {{ FOLDER }} in the if statement.
Like this:
{% set FOLDERS_TO_CLEAN = ['C:\Test\Folder1'] %}
{% for FOLDER in FOLDERS_TO_CLEAN %}
{% if salt['file.directory_exists']('{{ FOLDER }}') %}
{{ FOLDER }}_delete:
file.directory:
- name: {{ FOLDER }}
- clean: True
- failhard: True
{% endif %}
{% endfor %}

How to use variable as a match in saltstack mine.get

I am trying to use a salt mine to get a list of network interfaces of all the minions with the same os as that of the minion on which the jinja template is rendered.
I am trying something like this:
{% set variable = grains['os'] %}
{% set dict = salt['mine.get'('os:variable','network.interfaces','grain') %}
{% for i in dict : %}
// do stuff here
But the problem is in the above salt will try to match os to the value "variable" not to the actual value of the variable.
Using 'os: {{ variable }}' doesn't work too since {{ x }} just prints the value of variable x.
How can I match against the actual os in this case?
You should try + to concatenate prefix and variable name:
{% set variable = grains['os'] %}
{% set dict = salt['mine.get']('os:' + variable,'network.interfaces','grain') %}
{% for i in dict : %}
# do stuff
{% endfor %}

How can I check for file existence in salt file server

I want to copy ssh keys for users automatically, some users do not have keys.
What I have now is:
ssh_auth:
- present
- user: {{ usr }}
- source: salt://users/keys/{{usr}}.id_rsa.pub
When a key for a user does not exist on salt:// fileserver, I get an error. Is there some function to check for existence of a file in salt:// fileserver?
If you feel you MUST learn how to do this with just states, you can use the fallback mechanism by specifying a list of sources:
From the docs:
ssh_auth:
- present
- user:{{usr}}
- source:
- salt://users/keys/{{usr}}.id_rsa.pub
- salt://users/keys/null.id_rsa.pub
Where cat /dev/null > /srv/salt/users/keys/null.id_dsa.pub
Professionally, user keys should be stored in pillars. This presents the additional functionality that pillars are stored and retrieved from the master at execution time - which means you can test for the existence of the file per your original request. I do something just like that for openvpn certificates:
http://garthwaite.org/virtually-secure-with-openvpn-pillars-and-salt.html
I don't know of a jinja or salt function which can check the master's file server for a specific file. I would recommend you put those keys as a key in the pillar's file which contains your user's and use jinja to detect the existence of that key and create the key when necessary. For example:
The pillars file:
# Name of file : user_pillar.sls
users:
root:
ssh_key: some_key_value
home : /root
createhome: True
The state file:
# Name of file : users_salt_state_file.sls
{% for user,args in salt['pillar.get']('users',{}).iteritems() %}
# Ensure user is present
{{ user }}_user:
user.present:
- name: {{ user }}
# Home Creation
{% if args and 'home' in args %}
- home: {{ args['home'] }}
{% endif %}
{% if args and 'createhome' in args %}
- createhome: {{ args['createhome'] }}
{% endif %}
# SSH_auth
{% if args and 'ssh_key' in args %}
{{ args['ssh_key'] }}
ssh_auth:
- present
- user: {{ user }}
{% endfor %}

Unable to find template Symfony2

I would like to include a template in my view but it doesn't work, I have this error :
Unable to find template "::StyleBlock/light-pattern.html.twig" in ::base.html.twig at line 46.
My code :
{% for zone in content.blocks %}
{% set path = '::StyleBlock/' ~ zone.styles %}
{% include path %}
{% endfor %}
In the details i have this message :
InvalidArgumentException: The file "views/StyleBlock/light-pattern.html.twig" does not exist (in: /var/www/gathena/app/Resources).
But the path is correct, i don't understand.
I use Symfony 2.3 and I have the good permission on my directory
You have given wrong path, it should be:
{% for zone in content.blocks %}
{% set path = 'CmsCmsBundle:StyleBlock:' ~ zone.styles %}
{% include path %}
{% endfor %}
as for path src/Cms/CmsBundle/Resources/views/StyleBlock/
The first parameter is your bundle, second is the controller in this case StyleBlock, so your views are in your bundle in Resources/views/StyleBlock directory, last parameter is the template name which is defined by your loop variable in this case. It should only be your template name, without any absolute paths. All parameters are seperated by :
Try this :
::StyleBlock:light-pattern.html.twig

Resources