How to use if else in yaml? - yaml

Below is a snippet of yaml I am using. I want to call yaml say abc.yml if a variable ENV is set to, say 'abc', and xyz.yml if the variable ( passed as a parameter ) is set to 'xyz'. How do I use if condition in the yaml ?
script:
- ansible-playbook -i <dir> pqr.yaml --verbose -f 10 -e "ENV=${ENV}.... "
- ansible-playbook -i <dir> abc.yaml --verbose -f 10 -e "ENV=${ENV}.... "
- ansible-playbook -i <dir> xyz.yaml --verbose -f 10 -e "ENV=${ENV}.... "
- ansible-playbook -i <dir> hjk.yaml --verbose -f 10 -e "ENV=${ENV}.... "

Well you can, using conditions.
The example could be something like below:
I used an input parameter as example, any variable will do
I separated the scripts in jobs
Adding condition will take care of any validation and can therefore skip the job
parameters:
- name: whatToRunVar
displayName: 'What should it be: abc or xyz?'
default: ''
type: string
jobs:
- job: pqr
steps:
- script: ansible-playbook -i <dir> pqr.yaml --verbose -f 10 -e "ENV=${ENV}.... "
- job: abc
steps:
- script: ansible-playbook -i <dir> abc.yaml --verbose -f 10 -e "ENV=${ENV}.... "
condition: contains('${{ parameters.whatToRunVar}}', 'abc')
- job: xyz
steps:
- script: ansible-playbook -i <dir> xyz.yaml --verbose -f 10 -e "ENV=${ENV}.... "l
condition: contains('${{ parameters.whatToRunVar}}', 'xyz')
- job: hjk
steps:
- script: ansible-playbook -i <dir> hjk.yaml --verbose -f 10 -e "ENV=${ENV}.... "
Submitting abcde as parameter results in:

The following piece of code did the trick:
script:
- if [[ ${ENV} =~ "abc" ]]; then MODULE="abc"; else MODULE="xyz"; fi
- ansible-playbook -i $CI_PROJECT_DIR/ansible/${HOSTFILE} ${MODULE}_installation.yml --verbose -f 10 -e "ENV=${ENV}...

Related

Unterminated quoted string error while running 'kubectl exec' using shell

I am trying to run a kubectl exec command to run the command in the respective containers and transfer their outputs to a file using a shell script. I have the data in a YAML file with name of container, pod name, command and the file name where it is to be stored. I have parsed the YAML file using yq package and am trying to execute the commands. The commands having no quotes are executed successfully but the ones containing quotes result in an error. Collect execs contain name of the file and command.
I have tried running the commands normally on the command line and they seem to execute without any error. The error comes when I store them in a variable and then execute them.
Also doesn't work if I use " or ' or change ' to ".
FUNCTION
get_execs() {
mkdir ${EXECDIR}
for con in $(yq '.containers[] | .name' ${YFILE})
do
# echo $con
x=$(i=$con yq '.containers[] | select(.name == env(i)) | .collect_execs[] | .name' ${YFILE})
# printf "%s\n" "$x"
mkdir ${EXECDIR}/$con
for j in $x
do
c=$(i=$con p=$j yq '.containers[] | select(.name == env(i)) | .collect_execs[] | select(.name == env(p)) | .cmd' ${YFILE})
pod=$(i=$con yq '.containers[] | select(.name == env(i)) | .pod' ${YFILE})
# printf "%s abc\n" "$c"
kubectl exec -n ${NAMESPACE} $pod -c $con -- $c > ${EXECDIR}/$con/$j
done
done
}
YAML FILE STRUCTURE:
containers:
- name: otg-port-eth1-protocol-engine
pod: otg-port-eth1
collect_execs:
- name: resource-usage
cmd: top -c -n 2 -b -H -w 120
- name : disk-space
cmd : df -H
- name: cpu-info
cmd: cat /proc/cpuinfo
- name: interface-manager-threads-iter1
cmd : sh -c 'gdb --eval-command "set pagination 0" --eval-command "thread apply all bt" --batch --pid $(pidof InterfaceManager)'
- name: interface-manager-threads-iter2
cmd : sh -c 'gdb --eval-command "set pagination 0" --eval-command "thread apply all bt" --batch --pid $(pidof InterfaceManager)'
- name: interface-manager-shared-sos
cmd: sh -c 'cat /proc/$(pidof InterfaceManager)/maps'
- name: netstat
cmd: netstat -an
- name: dmesg
cmd : dmesg
- name : ifconfig
cmd : ifconfig
ERROR
--eval-command: 1: Syntax error: Unterminated quoted string
command terminated with exit code 2
--eval-command: 1: Syntax error: Unterminated quoted string
command terminated with exit code 2
/proc/$(pidof: 1: Syntax error: Unterminated quoted string
command terminated with exit code 2
--eval-command: 1: Syntax error: Unterminated quoted string
command terminated with exit code 2
--eval-command: 1: Syntax error: Unterminated quoted string
command terminated with exit code 2
/proc/$(pidof: 1: Syntax error: Unterminated quoted string
command terminated with exit code 2
The commands running with sh -c are causing the errors. To fix this, I changed the YAML structure and broke up the commands into 2 parts: precmd and cmd.
- name: resource-usage
cmd: top -c -n 2 -b -H -w 120
- name : disk-space
cmd : df -H
- name: cpu-info
cmd: cat /proc/cpuinfo
- name: interface-manager-threads-iter1
precmd : sh -c
cmd : 'gdb --eval-command "set pagination 0" --eval-command "thread apply all bt" --batch --pid $(pidof InterfaceManager)'
- name: interface-manager-threads-iter2
precmd : sh -c
cmd : 'gdb --eval-command "set pagination 0" --eval-command "thread apply all bt" --batch --pid $(pidof InterfaceManager)'
- name: interface-manager-shared-sos
precmd : sh -c
cmd: 'cat /proc/$(pidof InterfaceManager)/maps'
And then run the check:
if [ ! "$pc" = null ]
then
kubectl exec -n ${NAMESPACE} $pod -c $con -- $pc "$c" > ${EXECDIR}/$con/$j
else
kubectl exec -n ${NAMESPACE} $pod -c $con -- $c > ${EXECDIR}/$con/$j
fi
This seems to be working for me.

Execute bash script via ansible playbook

I'm looking to run the following shell script via ansible playbook.
#!/bin/bash
oci compute instance list --lifecycle-state RUNNING --region ca-toronto-1 --compartment-id < compartment OCID> --all | grep display-name -A 0 > hostnames.txt
for line in `cat hostnames.txt`
do
#echo $line
if [[ $line == *","* ]]; then
# hostname=$(echo ${line//"display-name"/} | tr -d '",: ')
hostname=$(echo "$line" | tr -d '",')
echo "$hostname"
ssh -tt "$hostname" "sudo puppet agent -tv && sleep 10"
# break
fi
done
This works just like how i want when i run the shell script but I get a blank output when i run via ansible.
Playbook:
---
- name: puppet agent trigger
gather_facts: false
become_user: true
hosts: all
tasks:
- name: trigger puppet agent
shell: |
oci compute instance list --lifecycle-state RUNNING --region ca-toronto-1 --compartment-id <compartment OCID> --all | grep display-name -A 0 > hostnames.txt
for line in `cat hostnames.txt`
do
if [[ $line == *","* ]]; then
hostname=$(echo "$line" | tr -d '",')
echo "$hostname"
ssh -tt "$hostname" "sudo puppet agent -tv && sleep 10"
fi
done
register: shell_output
- debug:
msg: "{{ shell_output.stdout }}"
Please point me as to what im missing.
According the description of your use case it seems to be recommended to transfer the whole logic of the script into Ansible itself. To do so and in respect to the comment regarding add_host_module, you could use an approach like
- name: Create an instance list
shell:
cmd: oc get nodes --no-headers | cut -d " " -f 1 | tr '\n' "," | rev | cut -c 2- | rev
register: instance_list
changed_when: false
To generate the instance_list I've used an OpenShift cluster as example, because I don't have something like oci compute instance list ... accessible.
- name: Add all hosts from instance_list to the script group
add_host:
name: '{{ item }}'
groups: script
loop: "{{ instance_list }}"
From there you could proceed further to execute your command puppet agent -tv && sleep 10.

/bin/sh: 1: Syntax error: Unterminated quoted string in dockerfile

I need to have variable inside file constants.js with quotes ('here variable'). Trying do it in dockerfile, but getting his error, can't figure it out. Tried escaping quotes, but its not working. Doing it with double quotes - works, but I need single. Any idea?
FROM debian:stretch-slim
ENV GIT_BRANCH=develop
ENV GIT_COMMIT_TAG=26bf94075e6d5f2c575a291680e905e15aa0c81f
COPY constants.js .
RUN { \
/bin/bash -c '{ \
sed -i -r "s/^([[:blank:]]*APP_VERSION:[[:blank:]]*).*/\1\'\${GIT_COMMIT_TAG:0:7}\',/" constants.js ; \
}' ; \
}
CMD ["sleep", "inf"]
File constants.js looks like:
const constants = {
APP_NAME: 'app',
APP_VERSION: '10.0.0',
};
module.exports = {
constants,
};
#UPDATE1
Longer
/bin/bash -c
in Dockerfile:
if [ ! -z "$GIT_BRANCH" ]; then \
GIT_BRANCH="${GIT_BRANCH}/" ; \
fi ; \
echo "${GIT_BRANCH}${GIT_COMMIT_TAG:0:7}" > .release.txt ; \
sed -i -r "s/^([[:blank:]]*APP_VERSION:[[:blank:]]*).*/\1'\${GIT_COMMIT_TAG:0:7}',/" constants.js ; \
appver=$(awk '"'"'/APP_VERSION/ { print $2 }'"'"' constants.js) ; \
echo "${appver:1:-2}" > .appversion ; \
so thats why I use bash -c.
You don't need to specify /bin/bash -c. Instead, just use RUN and immediately the command you need to execute. It is necessary to remove a few extra /. The final Dockerfile is given below
Dockerfile
FROM debian:stretch-slim
ENV GIT_BRANCH=develop
ENV GIT_COMMIT_TAG=26bf94075e6d5f2c575a291680e905e15aa0c81f
COPY constants.js .
RUN sed -i -r "s/^([[:blank:]]*APP_VERSION:[[:blank:]]*).*/\1\'$GIT_COMMIT_TAG:0:7',/" constants.js ;
CMD ["sleep", "inf"]
Resulted constants.js file
const constants = {
APP_NAME: 'app',
APP_VERSION: '26bf94075e6d5f2c575a291680e905e15aa0c81f:0:7',
};
module.exports = {
constants,
};
UPD #1
For execute some logic that does not fit on one line, the best solution would be to put it in a separate bash script.
Thus, you add setup.sh and change the Dockerfile
Dockerfile
FROM debian:stretch-slim
ENV GIT_BRANCH=develop
ENV GIT_COMMIT_TAG=26bf94075e6d5f2c575a291680e905e15aa0c81f
COPY ["constants.js", "setup.sh", "./"]
RUN chmod +x ./setup.sh && ./setup.sh
setup.sh
if [ ! -z "$GIT_BRANCH" ]; then
GIT_BRANCH="${GIT_BRANCH}/"
fi
CUTTED_GIT_COMMIT_TAG=$(echo "$GIT_COMMIT_TAG" | cut -c -7)
echo "${GIT_BRANCH}${CUTTED_GIT_COMMIT_TAG}" > .release.txt
sed -i -r "s/^([[:blank:]]*APP_VERSION:[[:blank:]]*).*/\1\'${CUTTED_GIT_COMMIT_TAG}',/" constants.js
APP_VERSION=$(awk '"'"'/APP_VERSION/ { print $2 }'"'"' constants.js)
CUTTED_APP_VERSION=$(echo "$appver" | cut -c 2- | rev | cut -c 1- | rev)
echo $CUTTED_APP_VERSION > .appversion
OK, so sed should looks like this:
sed -r -i "/APP_VERSION/ s/'\''(.*)'\''/'\''${GIT_COMMIT_TAG:0:7}'\''/" constants.js ; \
Then its working like it should.

How to pass value to ansible command module

I am new to ansible and trying to write some basic playbook. I need to run a command via command module, but that command needs use a value derived from other command this is what I have:
+++++++++++++++++++++++++++++++++++++++++++
---
- name: Post SentinelOne Agent
hosts: all
tasks:
- name: user sentinel exist
command: /usr/bin/grep sentinelone /etc/passwd
register: user_exist
ignore_errors: yes
- name: Create sentinelone user using existing id, only if the user does not exist
command: "useradd -d /opt/sentinelone/home/ -u `ls -ld /opt/sentinelone/ | awk '{print $3}'`** -f 1 -l -g sentinelone -s /sbin/nologin sentinelone"
when: user_exist.rc == 1
- name: Check again to confirm user exist for copy purpose
command: /usr/bin/grep sentinelone /etc/passwd
register: does_user_exist
ignore_errors: yes
- name: Whitelist sentinelone user ... Copy line from /etc/passwd
command: echo "`cat /etc/passwd | grep -i sentinelone`" >> /etc/crypt/passwd_local
when: does_user_exist.rc == 0
- name: Whitelist sentinelone user ... Copy line from /etc/shadow
command: echo "`cat /etc/shadow | grep -i sentinelone`" >> /etc/crypt/shadow_local
when: does_user_exist.rc == 0
+++++++++++++++++++++++++++++
get error:
for
command: "useradd -d /opt/sentinelone/home/ -u `ls -ld /opt/sentinelone/ | awk '{print $3}'`** -f 1 -l -g sentinelone -s /sbin/nologin sentinelone"
STDERR:
useradd: invalid user ID '`ls'
MSG:
non-zero return code

Ansible: escape quotes and listing users password expiry information

How to escape in shell module quotation?
I've tried as follows:
- name: UList
shell: "cut -f 1 -d: /etc/passwd | sudo xargs -n 1 -I {} bash -c \" echo {} ; chage -l {}\""
and
- name: UList
shell: "cut -f 1 -d: /etc/passwd | sudo xargs -n 1 -I {} bash -c \' echo {} ; chage -l {}\'"
Where is a mistake?
This playbook worked for me, hope this will be helpful for you too. You can use single quotes' for a command if you have an issue escaping " quote
Either do it this way
'cut -f 1 -d: /etc/passwd | sudo xargs -n 1 -I {} bash -c " echo {} ; chage -l {}"'
Or
"cut -f 1 -d: /etc/passwd | sudo xargs -n 1 -I {} bash -c ' echo {} ; chage -l {}'"
Both are working i have tested it.
---
- name: Set my hosts variable
hosts: localhost
tasks:
- name: UList
shell: 'cut -f 1 -d: /etc/passwd | sudo xargs -n 1 -I {} bash -c " echo {} ; chage -l {}"'
register: result
- name: debug
debug:
msg: "{{result}}"
Or
For the output you are expecting for that you can use
awk -F':' '{ system("echo " $1 " && chage -l " $1) }' /etc/passwd
Command explanation
---
- name: Set my hosts variable
hosts: localhost
tasks:
- name: UList
shell: "awk -F':' '{ system(\"echo \" $1 \" && chage -l \" $1) }' /etc/passwd"
register: result
- name: debug
debug:
msg: "{{result}}"

Resources