How to render variable within existing map - yaml

Edit: updated for clarity
I have a function that helps render a variable inside a map.
Example host.yaml
---
external:
"{{ testhost | tojson }}"
testhost is defined another file, so when the function renders the variable, the output will look like:
---
external:
host1: "here"
However when I add a second map to it, yamllint throws me an error:
Example of Issue:
---
external:
host2: "there"
"{{ testhost | tojson }}"
Yamllint shows this error:
(<unknown>): could not find expected ':' while scanning a simple key at line 4 column 3
Why wont it pass lint when I add another key value within the map?

Related

Is it possible to select an item within a list with a regex?

I am trying to create a script which is only selecting an item within a list, with a regex.
In my case, based on a certain condition which should be triggered wheter a specific character set is present of not within the name, then just select that item.
So far, I have produced the following code within an ansible Role:
- name: "Set_initial_regex"
set_fact:
name_regex: ".*((-a)+(\\d)?)\\..*\\.company\\..+"
# This regex should select any FQDN with "-a" followed by an optional number within its name (e.g. fqdn-test-a1.test.company.local)
- name: "Debug"
debug:
msg: "{{ name | split(',') | regex_search(name_regex) }}"
The name variable is provided with --extra-vars and could be multiple, but usually there are only two of them. They are separated by a comma - hence the split.
The code above works fine with | first and | last instead of regex_search, but I am looking for something more custom.
At the moment, the returned output is (for example):
"msg": [
"fqdn-test-a1.test.company.local",
"fqdn-test-b1.test.company.local"
]
And the desired output should -in this case- be just
"msg": [
"fqdn-test-a1.test.company.local"
]
Thanks in advance for any help or insights you might provide.
I found out the way to do this; the following code works fine for this purpose:
- name: "Debug"
debug:
msg: "{{ name | split(',') | select('search', name_regex) }}"
vars:
name_regex: ".*((-a)+(\\d)?)\\..*\\.company\\..+"
This returns the desired output mentioned above.
With select(), this works fine, as it should create a subset of a list, which is what I needed in this case.

Ansible, counting occurence of a word in a string

I am fairly new to Ansible, and I have been googling about this particular issue described below:
name: GETTING OUTPUT AND STORING IT INTO A VARIABLE
connection: network_cli
cli_command:
command: show configuration interface ge-0/0/0 | display set | match unit
register: A
Above, the task will run the command show configuration interface ge-0/0/0 on Juniper router, the out put will contain a bunch of key words unit. This output is then stored in a variable A.
I want to count the number of occurence key word unit appear in the output and store it in a variable COUNT. How can I do that? Ijust need an example.
Thanks and have a good weekend!!
If you have this task:
- name: get output and store
connection: network_cli
cli_command:
command: show configuration interface ge-0/0/0 | display set | match unit
register: show_config_result
Then you use a subsequent set_fact task to store the value you want in a variable:
- name: store unit count in unit_count variable
set_fact:
unit_count: "{{ (show_config_result.stdout_lines|length)-1 }}"

How to use variables between different roles in ansible

my playbook structure looks like:
- hosts: all
name: all
roles:
- roles1
- roles2
In tasks of roles1, I define such a variable
---
# tasks for roles1
- name: Get the zookeeper image tag # rel3.0
run_once: true
shell: echo '{{item.split(":")[-1]}}' # Here can get the string rel3.0 normally
with_items: "{{ret.stdout.split('\n')}}"
when: "'zookeeper' in item"
register: zk_tag
ret.stdout:
Loaded image: test/old/kafka:latest
Loaded image: test/new/mysql:v5.7
Loaded image: test/old/zookeeper:rel3.0
In tasks of roles2, I want to use the zk_tag variable
- name: Test if the variable zk_tag can be used in roles2
debug: var={{ zk_tag.stdout }}
Error :
The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'stdout'
I think I encountered the following 2 problems:
When registering a variable with register, when condition is added, this variable cannot be used in all groups. How to solve this problem? How to make this variable available to all groups?
is my title, How to use variables between different roles in ansible?
You're most likely starting a new playbook for a new host. Meaning all previous collected vars are lost.
What you can do is pass a var to another host with the add_host module.
- name: Pass variable from this play to the other host in the same play
add_host:
name: hostname2
var_in_play_2: "{{ var_in_play_1 }}"
--- EDIT ---
It's a bit unclear. Why do you use the when statement in the first place if you want every host in the play for it to be available?
You might want to use the group_vars/all.yml file to place vars in.
Also, using add_host should be the way to go as how I read it. Can you post your playbook, and the outcome of your playbook on a site, e.g. pastebin?
If there is any chance the var is not defined because of a when condition, you should use a default value to force the var to be defined when using it. While you are at it, use the debug module for your tests rather than echoing something in a shell
- name: Debug my var
debug:
msg: "{{ docker_exists | default(false) }}"

How to reference value stored in "register: " inside my jinja template? { the output in register are show command outputs }

I am trying to write the output of a series of show commands to a text file on Ansible. My approach is to reference the registers on my jinja2 template. I am unclear on how to reference these register values if the return type is not a dictionary/list. How do I reference these variables in my template ?
I have tried calling them as msg."register name". This writes to the file, but is haphazard with barely any formatting structure.
Part of my Playbook
register: int_status
- set_fact:
int_status={{ int_status.stdout }}
- name: Print the interface status
debug:
msg: "{{ int_status }}"
My jinja2 file:
Host information:
------------------------------
ip address: {{device_info.ansible_facts['ansible_net_all_ipv4_addresses']}}
Interfaces: {{msg}}

Using variables for file name and file contents in lineinfile module

I am trying to read the contents of a file, store these in a variable and then insert them into another file if they don't already exist.
So, how I'm attempting to go about this is as follows:
# Create a variable that represents the path to the file that you want to read from
ssh_public_key_file: '../../jenkins_master/files/{{ hostvars[inventory_hostname]["environment"] }}/id_rsa.pub'
# Create a variable that represents the contents of this file:
ssh_public_key: "{{ lookup('file', '{{ ssh_public_key_file }}') }}"
I then use these variables in my Ansible playbook as follows:
- name: Install SSH authorized key
lineinfile: create=yes dest=~/.ssh/authorized_keys line=" {{ ssh_public_key }}" mode=0644
However, when I try and run the playbook, I get the following error message:
could not locate file in lookup: {{ ssh_public_key_file }}
Can anyone recommend a solution or suggest what I may have done wrong?
Thanks,
Seán
You have to change the line to:
# Create a variable that represents the contents of this file:
ssh_public_key: "{{ lookup('file', ssh_public_key_file) }}"
If you need to concatenate variables and strings you can do it like this:
# Example with two variables
ssh_public_key: "{{ lookup('file', var_1+var_2) }}"
# Example with string and variable
ssh_public_key: "{{ lookup('file', '~/config/'+var_1) }}"
. .
First I would make sure that your ssh_public_key_file variable is set up properly. If you add a task like the following what does it show?
- name: display variable
debug: var=ssh_public_key_file
If the output looks something like this then the variable isn't defined properly (eg. the "environment" fact doesn't exist for the host):
ok: [localhost] => {
"ssh_public_key_file": "../../jenkins_master/files/{{ hostvars[inventory_hostname][\"environment\"] }}/id_rsa.pub"
}
However if everything is defined properly then your output should show the variables replaced with their correct values:
ok: [localhost] => {
"ssh_public_key_file": "../../jenkins_master/files/foo/id_rsa.pub"
}
Once you've verified that then I would do the same thing with your ssh_public_key variable. Just output its value using the debug module. It should display as the contents of the public key file.
One other thing I would strongly suggest is to avoid using lineinfile altogether. Since you're working with SSH keys I would recommend you use the authorized_key module instead. It's a much cleaner way of managing authorized_keys files.

Resources