How to symlink in saltstack latest version or file - salt-stack

ln -fs /opt/app/$(ls -rt file-*.jar | tail -n1) /opt/app/file.jar
works in bash very well
dir contains
file-1.jar
file-2.jar
file-3.jar
How can I do this in a salt stack state sls formula ?

To achieve this in Saltstack we need roughly two steps:
Get the latest file
Link the file
For the first part, we can use some salt module such as file.find, but I feel the existing logic of using ls -rt is simpler.
So we can use this command to get the latest JAR file into a variable. Then use a Salt state to link the file.
Example:
{% set latest_jar = salt.cmd.run('ls -rt /opt/app/file-*.jar | tail -n1') %}
link-latest-jar:
file.symlink:
- name: /opt/app/file.jar
- target: {{ latest_jar }}
Update:
With newer version of Saltstack we need to use salt.cmd.shell to set the latest_jar variable.

{% set latest_jar = salt['cmd.shell']('ls -rt /opt/app/file-*.jar | tail -n1') %}
link-latest-jar:
file.symlink:
- name: /opt/app/file.jar
- target: {{ latest_jar }}
works for me... thx for help

Related

Ansible Fetch Quote Error

I am trying to retrieve a file from a remote host. However, after looking at some examples on stackoverflow, the bottom two methods result in the follow errors:
- shell: ls -f ubuntu_s*
register: file_name
- fetch: src=/home/ubuntu/{{file_name.stdout_lines}} dest=/home/user
- shell: ls -f ubuntu_s*
register: file_name
- fetch: src={{item}} dest=/home/user
with_items: "{{file_name.stdout_lines}}"
Error:
ERROR! this task 'fetch' has extra params, which is only allowed in the following modules: command, shell, script, include, include_vars, add_host, group_by, set_fact, raw, meta
The error appears to have been in '/home/user/BuildPkg.yml': line 49, column 7, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
register: file_name
- fetch: src=/home/ubuntu/{{file_name.stdout_lines}} dest=/home/user
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
The error appears to have been in '/home/user/BuildPkg.yml': line 49, column 7, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
register: file_name
- fetch: src=/home/ubuntu/{{file_name.stdout_lines}} dest=/home/user
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
Both approaches give the same error. What seems to be wrong?
Try to avoid shell where possible. Modules – this is the Ansible way.
If you need to get a list of files from remote host and fetch them:
- find:
pattern: ubuntu_s*
path: /home/ubuntu/
register: myfiles
- fetch:
src: "{{ item.path }}"
dest: /home/user
flat: yes
with_items: "{{ myfiles.files }}"
The correct way is looping over file globs, like:
- fetch: src={{ item }} dest=/home/user
with_fileglob:
- ubuntu_s*
Note: know what you may face whenever trying to parse ls output

ROBOT framework: using environment variables in argument file

Here's a basic rundown of what I want to do:
I want to call my scripts using an argument file. But the argument file needs to work on an environment variable for the path. So, for example, the argument file may be:
args.robot
[ROBOT_HOME variable]/test1.robot
[ROBOT_HOME variable]/test2.robot
[ROBOT_HOME variable]/test3.robot
And I would define the ROBOT_HOME variable at the environment level:
$ export ROBOT_HOME=/path/to/tests/
$ pybot -A args.robot
None of the following substitutions for [ROBOT_HOME variable] in the args.robot file have worked:
$ROBOT_HOME
${ROBOT_HOME}
%{ROBOT_HOME}
And neither of the following pybot commands have worked:
pybot -A args.robot
pybot -v ROBOT_HOME:$ROBOT_HOME -A args.robot
Is what I'm trying to do possible?
#Rao gives a good solution for the problem. The last part of the documentation on arguments file demonstrate how to programmatically generate argumentfile and use them with a one-liner.
generate_arguments.sh | robot --argumentfile STDIN
generate_arguments.sh | robot --name Example --argumentfile STDIN tests.robot
The quesion remaining now is what can the generate_arguments.sh be? Il like to use envsub, envsub replace environnement variables in a script (for linux env)
envsubst '$HOME' < "argumentfile.txt" > "argumentfile.txt"
echo "argumentfile.txt"
Another possibility to run that script would be:
generate_arguments.sh && robot --argumentfile "argumentfile.txt"
#xNok Solution would work, but it is not very accurate. You can not rewrite a file with envsubst command. Take a look into this thread.
rewriting a file with "envsubst file" leaves it empty
So, basically if you want to get it working in this way, the argument file would look like this:
export HOME='your/path'
envsubst '${HOME}' < argumentfile.txt > argumentfile_tmp.txt && mv argumentfile_tmp.txt argumentfile.txt
And for instance the "argumentfile.txt" would look like this:
--variable PATH:${HOME}/some/sub/path
Then as suggested by #xNok, you can run the script this way:
generate_arguments.sh && robot --argumentfile "argumentfile.txt"
Please note that this method would overwrite the "argumentfile.txt". So, every time you need to clone the source code or the other option is to use envsubst to write to a temporary file.

Check file exists and create a symlink

I want to do something like that:
if file A exists or there is no symlink B, I want to create a symlink B -> A.
For now I have:
B:
file:
- symlink:
- target: A
- exists:
- name: A
But this is bad it checks not the thing I want. How can I achive this simple thing in salt ?
We can use file.directory_exists
{% if not salt['file.directory_exists' ]('/symlink/path/A') %}
symlink:
file.symlink:
- name: /path/to/A
- target: /symlink/path/A
{% endif %}
You should use Dan Garthwaite's excellent answer here as a basis for how to check for the existence of a file. I have modified his solution to answer your question.
{% if 1 == salt['cmd.retcode']('test -f /path/to/A') %}
/path/to/A:
file.symlink:
- target: /symlink/path/A
{% endif %}
/path/to/symlink/B:
file.symlink:
- target: /path/to/target/A
- onlyif:
- test -f /path/to/target/A # check that the target exists
- test ! -L /path/to/symlink/B # check that B is not a symlink
This will require both conditions to be True for the symlink to be created. Note that -L will also return 1 (False) if the file exists but is not a symlink.
From the docs:
The onlyif requisite specifies that if each command listed in onlyif returns True, then the state is run. If any of the specified commands return False, the state will not run.
NOTE: Under the hood onlyif calls cmd.retcode with python_shell=True. This means the commands referenced by onlyif will be parsed by a shell, so beware of side-effects as this shell will be run with the same privileges as the salt-minion. Also be aware that the boolean value is determined by the shell's concept of True and False, rather than Python's concept of True and False.

How to make zsh search configuration in $XDG_CONFIG_HOME

Looking to make my ~ a cleaner place, I would like to move as much user configuration files into $XDG_CONFIG_HOME, which is ~/.config by default. So I would like to store all my zsh user files in $XDG_CONFIG_HOME/zsh/. So far already have this:
% ls $XDG_CONFIG_HOME/zsh/
histfile zsh_cache zshrc
Easy, you just have to fill your ~/.zshrc. Now the trickiest part seems to make zsh read directly $XDG_CONFIG_HOME/zsh/zshrc without sourcing it from ~/.zshrc. How would you proceed?
One may edit /etc/zsh/zshenv to set $XDG_CONFIG_HOME directories and $ZDOTDIR. This require write privilegies on this files though.
So provided that $HOME is defined when zsh read it (I don't know if it's the case), you may add to your /etc/zsh/zshenv:
if [[ -z "$XDG_CONFIG_HOME" ]]
then
export XDG_CONFIG_HOME="$HOME/.config/"
fi
if [[ -d "$XDG_CONFIG_HOME/zsh" ]]
then
export ZDOTDIR="$XDG_CONFIG_HOME/zsh/"
fi
It is good practice to not put a / at the end of any variable holding a certain path.
For example, $XDG_CONFIG_HOME/zsh translates to "$HOME/.config//zsh" and the / repeats because XDG_CONFIG_HOME ends with a /.
So I think your answer should be -
if [[ -z "$XDG_CONFIG_HOME" ]]
then
export XDG_CONFIG_HOME="$HOME/.config"
fi
if [[ -d "$XDG_CONFIG_HOME/zsh" ]]
then
export ZDOTDIR="$XDG_CONFIG_HOME/zsh"
fi
Variation to psychoslave's answer which uses ${HOME}/.zshenv to initiate the environment. No root access needed.
export XDG_CONFIG_HOME=${XDG_CONFIG_HOME:=${HOME}/.config}
export ZDOTDIR=${ZDOTDIR:=${XDG_CONFIG_HOME}/zsh}
source $ZDOTDIR/.zshenv
This was discussed on this thread on the zsh-users mailing list.
You may want to consider saving history in XDG_DATA_HOME. Specifications can be found at XDG Base Directory Specification.
Write a wrapper for zsh that executes zsh after setting the environment variable ZDOTDIR to where you want zsh to look for the config files.
See: http://zsh.sourceforge.net/Intro/intro_3.html

ZSH auto_vim (like auto_cd)

zsh has a feature (auto_cd) where just typing the directory name will automatically go to (cd) that directory. I'm curious if there would be a way to configure zsh to do something similar with file names, automatically open files with vim if I type only a file name?
There are three possibilities I can think of. First is suffix aliases which may automatically translate
% *.ps
to
% screen -d -m okular *.ps
after you do
alias -s ps='screen -d -m okular'
. But you need to define this alias for every file suffix. It is also processed before most expansions so if
% *.p?
matches same files as *.ps it won’t open anything.
Second is command_not_found handler:
function command_not_found_handler()
{
emulate -L zsh
for file in $# ; do test -e $file && xdg-open $file:A ; done
}
. But this does not work for absolute or relative paths, only for something that does not contain forward slashes.
Third is a hack overriding accept-line widget:
function xdg-open()
{
emulate -L zsh
for arg in $# ; do
command xdg-open $arg
endfor
}
function _-accept-line()
{
emulate -L zsh
FILE="${(z)BUFFER[1]}"
whence $FILE &>/dev/null || BUFFER="xdg-open $BUFFER"
zle .accept-line
}
zle -N accept-line _-accept-line
. The above alters the history (I can show how to avoid this) and is rather hackish. Good it does not disable suffix aliases (whence '*.ps' returns the value of the alias), I used to think it does. It does disable autocd though. I can avoid this (just || test -d $FILE after whence test), but who knows how many other things are getting corrupt as well. If you are fine with the first and second solutions better to use them.
I guess you can use "fasd_cd" which has an alias v which uses viminfo file to identifi files which you have opened at least once. In my environment it works like a charm.
Fast cd has other amazing stuff you will love!
Don't forget to set this alias on vim to open the last edited file:
alias lvim="vim -c \"normal '0\""

Resources