Ansible trim string - ansible

I'm trying write role to install MySql 8, and get problem with this:
- name: Extract root password from logs into {{ mysql_root_old_password }} variable
ansible.builtin.slurp:
src: "{{ mysql_logfile_path }}"
register: mysql_root_old_password
#when: "'mysql' in ansible_facts.packages"
- name: Extract root password from logs into {{ mysql_root_old_password }} variable
set_fact:
mysql_root_old_password: "{{ mysql_root_old_password.content | b64decode | regex_findall('generated for root#localhost: (.*)$', 'multiline=true') }}"
#when: "'mysqld' in ansible_facts.packages"
- name: Get Server template
ansible.builtin.template:
src: "{{ item.name }}.j2"
dest: "{{ item.path }}"
loop:
- { name: "my.cnf", path: "/root/.my.cnf" }
notify:
- Restart mysqld
on the .my.cnf I get password with quotes and brackets:
[client]
user=root
password=['th6k(gZeJSt4']
How to trim that?
What I try:
- name: trim password
set_fact:
mysql_root_old_password2: "{{ mysql_root_old_password | regex_findall('[a-zA-Z0-9,()!##$%^&*]{12}')}}"
Thanks.

The result of regex_findall is a list because there might be more matches. Take the last item
- set_fact:
mysql_root_old_password: "{{ mysql_root_old_password.content|
b64decode|
regex_findall('generated for root#localhost: (.*)$', 'multiline=true')|
last }}"

From your description
on the .my.cnf I get password with quotes and brackets ... How to trim that
I understand that you like to read a INI file like my.cnf.ini
[client]
user=root
password=['A1234567890B']
where the value of the key password looks like a list with one element in YAML and the structure doesn't change, but you are interested in the value without leading and trailing square brackets and single quotes only.
To do so there are several possibilities.
Via Ansible Lookup plugins
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Extract root password from INI file
debug:
msg: "{{ lookup('ini', 'password section=client file=my.cnf.ini') }}"
register: result
- name: Show result with type
debug:
msg:
- "{{ result.msg }}"
- "result.msg is of type {{ result.msg | type_debug }}"
- "Show password only {{ result.msg[0] }}" # the first list element
Such approach will work on the Control Node.
Like all templating, lookups execute and are evaluated on the Ansible control machine.
Further Q&A
How to read a line from a file into an Ansible variable
What is the difference between .ini and .conf?
Further Documentation
ini lookup – read data from an INI file
Via Ansible shell module, sed and cut.
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Extract root password from INI file
shell:
cmd: echo $(sed -n 's/^password=//p' my.cnf.ini | cut -d "'" -f 2)
register: result
- name: Show result
debug:
msg: "{{ result.stdout }}"
Please take note regarding "I get password with quotes and brackets ... ['<pass>'] ... How to trim that?" that from perspective of the SQL service, .cnf file, [' and '] are actually part of the password!
- name: Server template
template:
src: "my.cnf.ini"
dest: "/root/.my.cnf"
If that is correct they will be necessary for proper function of the service.

Related

set path when file exists in Ansible yml code

I'm trying to set a var only when a file exists, here is one of my attempts
---
- hosts: all
tasks:
- stat:
path: '{{ srch_path_new }}/bin/run'
register: result
- vars: srch_path="{{ srch_path_new }}"
when: result.stat.exists
This also didn't work
- vars: srch_path:"{{ srch_path_new }}"
The task you are looking for is called set_fact: and is the mechanism ansible uses to declare arbitrary "host variables", sometimes called "hostvars", or (also confusingly) "facts"
The syntax would be:
- set_fact:
srch_path: "{{ srch_path_new }}"
when: result.stat.exists
Also, while vars: is a legal keyword on a Task, its syntax is the same as set_fact: (or the vars: on the playbook): a yaml dictionary, not a key:value pair as you had. For example:
- debug:
msg: hello, {{ friend }}
vars:
friend: Jane Doe
and be aware that vars: on a task exist only for that task

How to pass variable value from command parameter and use it in with_items:?

For me the below code is working -
with_items: "{{ groups['mlpoc'] }}" but instead of hardcoded mlpoc I want to pass it in a variable as a parameter.
Say the command parameter is mlhosts=mlpoc and I want to use the variable instead of hardcoded value, something like -
with_items: "{{ groups['{{ mlhosts }}'] }}" but it throws error. Is it even possible to pass a dynamic value to groups ?
Here is my code -
- hosts: dbsrd3510
user: '{{ mluser }}'
gather_facts: no
no_log: false
tasks:
- name: Fetch source list from clients
with_items: "{{ groups['mlpoc'] }}"
shell: rsync -av /MLbackup/{{ pkg }} {{ mluser }}#{{ item }}:/tmp/
Try something like this,
---
- hosts: all
gather_facts: no
tasks:
- name: Add a line to a file if the file does not exist, without passing regexp
debug:
msg: "{{ item }}"
with_items: " {{ groups[group_name] }} "
And you can test the above changes using,
ansible-playbook -i hosts main.yml -e group_name="all"

Use registered variables in other roles

Hello guys I have a Problem.
The Problem I am having at the moment, is that the role to copy the files will skip all the files no matter if the file with the filenames is empty or not.
In Role1 I want to save the output of cat for each file. In Role2 in the when conditional, I want the task to skip if the registered output is == "".
Role1:
---
- name: copy files
shell: "cat path{{ item }}files"
register: checkempty
loop:
- test1
- test2
- test3
- test4
Role2:
---
- name: Copy Files
copy:
src: "{{ var1 }}{{ var2 }}{{ var3 }}{{ var4 }}{{ item }}/"
dest: "{{ copy_dest_sys }}" #destination path
loop: "{{ lookup('file', 'pathtofile/file').split('\n')}}"
when: hostvars['localhost'].checkempty.results == ""
Playbook:
- name: check emptiness
hosts: localhost
become: yes
vars_files:
- ../variables/varsfile
roles:
- ../variables/role1
- name: Copy Files to prod/stag
hosts: "{{hosts_exec}}"
become: yes
vars_files:
- ../vars/recommendation-delta.yml
roles:
- ../roles/role2
How can I set a registered variable with with_items and compare the output of it to ""(nothing)?
Can somebody help me with this issue?
When you register a variable, it is set only on the specific host on which that task was executing. So if you are running a role on localhost that does this:
---
- name: Check if sys files Empty
command: if [ ! -s filenames/"{{ item }}"files ]; then echo "{{ item }}fileempty"; fi
register: checkempty
loop:
- sys
- wifi
- recoprop
- udfprop
Then you would reference it like this when running tasks on another host:
hostvars["localhost"].checkempty
For example:
---
- name: Copy sys Files to prod/stag
copy:
src: "{{ git_dest }}{{ git_sys_files }}{{ item }}/"
dest: "{{ copy_dest_sys }}" #destination path
loop: "{{ lookup('file', '/home/ansible/repo/hal_ansible/scripts/delta-reco/filenames/sysfiles').split('\n')}}"
when: 'hostvars["localhost"].checkempty.stdout == "sysfileempty"'
You can read more about this in the "Using Variables" documentation.
I've made some corrections to your when syntax here as well. In general, you should never use {{...}} markers in a when condition because a when condition is always evaluated as a Jinja expression.
However, you have another problem:
Your "Check if sys files Empty" task is using the command module, but you're trying to run a shell script. That will always fail. You need to use the shell module instead:
---
- name: Check if sys files Empty
shell: if [ ! -s filenames/"{{ item }}"files ]; then echo "{{ item }}fileempty"; fi
register: checkempty
loop:
- sys
- wifi
- recoprop
- udfprop

Playbook where item.stat.exist not working

I have created playbook which will run on a remote host and check whether the files exist or not. I want to extract the only files which are not present on the remote host. But my playbook giving all paths whether they are present or not.
Playbook:-
- name: Playbook for files not present on remote hosts
hosts: source
gather_facts: false
vars:
Filepath: /opt/webapps/obiee/oracle_common/inventory/ContentsXML/comps.xml
tasks:
- name: Getting files location path
shell: grep -i "COMP NAME" {{ Filepath }} |sed 's/^.*INST_LOC="//'|cut -f1 -d'"' | sed '/^$/d;s/[[:blank:]]//g' // extract files from comps.xml
register: get_element_attribute
- name: check path present or not
stat:
path: "{{ item }}"
with_items:
- "{{ get_element_attribute.stdout_lines }}"
register: path_output
- name: path exists or not
set_fact:
path_item: "{{ item }}" # here i am getting the output as expected that's files not present on remote host
with_items: "{{ path_output.results }}"
register: final_output
when: item.stat.exists == False
- debug:
var: final_output # giving both output i.e. files present and absent
- name: Create a fact list
set_fact:
paths: "{{ final_output.results | map(attribute='item.item') | list }}" # i have add this condition " item.stat.exists == False' inside this stmt
- name: Print Fact
debug:
var: paths
The issue resolved by using below command:
- name: Create a fact list
set_fact:
paths: "{{ final_output.results | selectattr('item.stat.exists', 'equalto', false) | map(attribute='item.item') | list }}"
register: config_facts
The following query should get all the file names which don't exsist on the remote host and store them in the fact 'paths':
- name: Create a fact list
set_fact:
paths: "{{ final_output | json_query(query)}}"
vars:
query: "results[?(#._ansible_item_label.stat.exists==`false`)]._ansible_item_label.item"

Return Variable from Included Ansible Playbook

I have seen how to register variables within tasks in an ansible playbook and then use those variables elsewhere in the same playbook, but can you register a variable in an included playbook and then access those variables back in the original playbook?
Here is what I am trying to accomplish:
This is my main playbook:
- include: sub-playbook.yml job_url="http://some-jenkins-job"
- hosts: localhost
roles:
- some_role
sub-playbook.yml:
---
- hosts: localhost
tasks:
- name: Collect info from Jenkins Job
script: whatever.py --url "{{ job_url }}"
register: jenkins_artifacts
I'd like to be able to access the jenkins_artifacts results back in main_playbook if possible. I know you can access it from other hosts in the same playbook like this: "{{ hostvars['localhost']['jenkins_artifacts'].stdout_lines }}"
Is it the same idea for sharing across playbooks?
I'm confused what this question is about. Just use the variable name jenkins_artifacts:
- include: sub-playbook.yml job_url="http://some-jenkins-job"
- hosts: localhost
debug:
var: jenkins_artifacts
This might seem complicated but I love doing this in my Playbooks:
rc defines the name of the variable which contains the return value
ar gives the arguments to the include tasks
master.yml:
- name: verify_os
include_tasks: "verify_os/main.yml"
vars:
verify_os:
rc: "isos_present"
ar:
image: "{{ os.ar.to_os }}"
verify_os/main.yml:
---
- name: check image on device
ios_command:
commands:
- "sh bootflash: | inc {{ verify_os.ar.image }}"
register: image_check
- name: check if available
shell: "printf '{{ image_check.stdout_lines[0][0] }}\n' | grep {{ verify_os.ar.image }} | wc -l"
register: image_available
delegate_to: localhost
- set_fact: { "{{ verify_os.rc }}": "{{ true if image_available.stdout == '1' else false }}" }
...
I can now use the isos_present variable anywhere in the master.yml to access the returned value.

Resources