Ansible Different hosts, different action - variables

with Ansible I need to copy a script in different clients/hosts, then I need to modify a line in the script. The line depends of the client and is not the same each times.
Each hosts have the same name. Each clients name is different.
Something like that:
lineinfile: >
state=present
dest=/path/to/myscript
line="/personal line
when: {{ clients/hosts }} is {{ client/host }}
As you can see, I have no idea about the way to proceed.

It sounds like there are some clients that have some specific hosts associated to them, and the line in this script will vary based on the client.
In that case, you should use group vars. I've included a simplified example below.
Set up your hosts file like this:
[client1]
host1
host2
[client2]
host3
host4
Use group variables like this:
File group_vars/client1:
variable_script_line: echo "this is client 1"
File group_vars/client2:
variable_script_line: echo "this is client 2"
Create a template file named yourscript.sh.j2:
#!/bin/bash
# {{ ansible_managed }}
script line 1
script line 2
# below is the line that should be dynamic
{{ variable_script_line }}
And then use the template module like this:
---
- hosts: all
tasks:
- name: Deploy script to remote hosts
template:
src: /path/to/yourscript.sh.j2
dest: /path/to/location/yourscript.sh
mode: 0755
Note that the path to your source template will be different if you're using a [role][1].
Ultimately, when the play is run on client1 vs client2, the content of the template will be written differently based on the variable (see more about variable scopes).

Related

how to call a dictionary variable from ansible host_var to ansible playbook

I have an ansible playbook, which has a variable defined in it like this:
- hosts: dev-web
become: yes
vars:
- web_dir: /opt/abc/example.com/xyz
i want the string inside the variable "/opt/abc/example.com/xyz" dynamically get from the host_var file in host_vars/dev-web.
host_var file looks like this:
vhosts:
dev1:
name: 'example.com'
dev2:
name: 'xyz.com'
Expected outcome dev1 is:
vars:
web_dir: /opt/abc/"{{ vhosts.dev1.name }}"/xyz
should reflect to
web_dir: /opt/abc/example.com/xyz
and for dev2:
vars:
web_dir: /opt/abc/"{{ vhosts.dev2.name }}"/xyz
should reflect to
web_dir: /opt/abc/xyz.com/xyz
Any help would be appreciated.
You have to approach the problem from a different perspective:
In the playbook, the variable should be identical for all hosts, i.e. vhost.name, which will take a different value in every host.
In the host_vars/ directory, you should have a different file for each host.
File host_vars/dev1:
vhost:
name: dev1
File host_vars/dev2:
vhost:
name: dev2
On another note, if possible, I'd rather reuse the real hostname using an automatically generated variable like: ansible_host or inventory_hostname.

Ansible: How to use examples from the documentation?

I'm starting to learn Ansible and for this I copy and paste examples from the documentation. For example this one
- name: Check that a page returns a status 200 and fail if the word AWESOME is not in the page contents
ansible.builtin.uri:
url: http://www.example.com
return_content: yes
register: this
failed_when: "'AWESOME' not in this.content"
which I've found in uri module documentation.
Every single time I do this, whatever the module I get:
ERROR! 'ansible.builtin.uri' is not a valid attribute for a Play
The error appears to have been in '/home/alfrerra/test2.yml': line 1, column 3, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: Check that a page returns a status 200 and fail if the word AWESOME is not in the page contents
^ here
I have only 2 playbooks that only ping successfully:
-
name: ping localhost
hosts: localhost
tasks:
- name: ping test
ping
and
---
- name: ping localhost
hosts: localhost
tasks:
- name: ping test
ping
So I adapted the example to match these 2 examples, but to no avail so far.
I'm sure it's nothing much but it's driving me crazy.
As already mentioned within the comments, the documentation are to show how to use certain parameter of certain modules within a single task. They are not mentioned to work in a copy and paste manner by itself or only.
You may have a look into the following minimal example playbook
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Check that a page returns a status 200 and fail if the word 'iana.org' is not in the page contents
uri:
url: http://www.example.com
return_content: yes
environment:
http_proxy: "localhost:3128"
https_proxy: "localhost:3128"
register: this
failed_when: "'iana.org' not in this.content"
- name: Show content
debug:
msg: "{{ this.content }}"
resulting into the output of the page content.
Please take note that the web page of the example domain is connected and delivers a valid result, but it does not contain the word AWESOME. To address this the string to lookup was changed to the page owner iana.org and to not let the task fail. Furthermore and since working behind a proxy it was necessary to address the proxy configuration and which you probably need to remove again.
Your first example is a single task and failing therefore with ERROR! ... not a valid attribute for a Play. Your second and
third examples are playbooks with a single task and therefore executing.
Documentation
Module format and documentation - EXAMPLES block
... show users how your module works with real-world examples in multi-line plain-text YAML format. The best examples are ready for the user to copy and paste into a playbook.
Ansible playbooks
failed_when must be a comparison or a boolean.
example :
- name: Check that a page returns AWESOME is not in the page contents
ansible.builtin.uri:
url: http://www.example.com
return_content: yes
register: this
failed_when: this.rc == 0;
It will execute the task only if the return value is equal to 0

Include variables generated in first play of playbook

I have a playbook which consists of two plays:
1: Create inventory file and variables file on localhost
2: Use the variables in commands on generated inventory
Example playbook:
---
- name: Generating inventory and variables
hosts: localhost
vars_files:
- variables.yml #variables file used for automating
tasks:
- name: Creating inventory template
template:
src: hosts.j2
dest: "./inventories/{{location}}/hosts"
mode: 0777
force: yes
ignore_errors: yes
run_once: true
- meta: refresh_inventory
- name: Creating predefined variables from a template
template:
src: predefined-vars.yml.j2
dest: "./variables/predefined-vars.yml"
- name: Setting vlan to network devices
remote_user: Ansible
hosts: all
vars_files:
- variables.yml #variables file used for automating.
- variables/predefined-vars.yml
tasks:
- name: configure Junos ROUTER for vlan
include_tasks: ./roles/juniper/tasks/add_vlan_rt.yml
when:
- inventory_hostname in groups['junos_routers']
- groups['junos_routers'] | length == 1
- location == inventory_name
This gives undefined variable error (for a variable created in the first play).
Is there a way to do this? I use this for generating variables like router_port_name and so on - the variables depend on location and dedicated server, which are defined in variables.yml
Any help is really appreciated.
Thanks
EDIT: However, I have noticed that this playbook:
---
- hosts: localhost
gather_facts: false
name: 1
vars_files:
- variables.yml
tasks:
- name: Creating predefined variables from a template
template:
src: predefined-vars.yml.j2
dest: "./variables/predefined-vars.yml"
- name: Generate hosts file
hosts: all
vars_files:
- variables.yml
- ./variables/predefined-vars.yml
tasks:
- name: test
debug: msg="{{ router_interface_name }}"
show the variables created in the first play.
The difference I see is that the first playbook reads all variable files (even predefined-vars.yml <- created at first play, used at the other) used in the playbook at the start of the first play (generating inventory and creating variable file) while the second playbook reads variables.yml in first play and only at the start of the second play reads the predefined-vars.yml .
Any Ideas how to make the first playbook behave the same way?
So I have found the solution to the problem, based on the documentation and suggestions from other people.
What I understood about the problem:
A playbook will read all the variables (of all plays) provided into the cache for later use, so if I include my predefined-vars.yml into vars_files, then after changing it in first play, the changes will not be used by later plays because they will use cache for that.
Thus I had to create another task in second play, which would read (load into cache) my newly generated file (for that play):
- name: Include predefined vars
include_vars: ./variables/predefined-vars.yml
run_once: true
Hope this helps you!
Still have no idea why second play shows the variables...

Ansible: Variables defined under defaults are not loaded in to my playbook

I have defined a role dcn-rq2 and it has some variables defined in
~/dcn-rq2/defaults/main.yml file and i have written a playbook which includes this role at the top as shown below. my understanding is that all the vraiables defined in the role should automatically available to the playbook but it errors out.
//My top level YAML file for the playbook
- hosts: DCN-VSD
roles:
- dcn-rq2
tasks:
- debug: msg="{{test_var}}"
my dcn-rq2/defaults/main.yml
---
test_var: '12'
Defaults is something you use on roles. Playbooks use host_vars & groups_vars directories to include variables.
To add a global 'variable' shared across all your playbooks, place a 'all.yml' file in the group_vars directory.
More information can be found here:
http://docs.ansible.com/ansible/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable
I just tried this and it works. The only difference I could see in your playbook is that the tasks section is not indented correctly. But I am assuming it changed when you copy/pasted it here.
---
- hosts: localhost
remote_user: root
roles:
- common
tasks:
- debug: msg="{{test_var}}"
Also you said
my understanding is that all the vraiables defined in the role should automatically available to the playbook
All the variables defined in the role will be available to the play you associate the role with in your playbook. In your case the only play in your playbook. So this should still work.

Defining Variable Configuration in _config.yml in jekyll powered website

There are multiple sets of configuration which you may want to execute when you are running the site locally while when your site is running on server (say Github).
I have defined similar set of configuration in my _config.yml file like this
title: Requestly
locale: en_US
description: Chrome Extension to modify HTTP(s) Requests
logo: site-logo.png
search: true
env: dev
config:
dev:
url: http://localhost:4000
prod:
url: http://requestly.github.io/blog
url: site.config[site.env].url // Does not work
I have used {{ site.url }} everywhere else in my templates, layouts and
posts.
How can I define site.url in my _config.yml file whose value depends upon the config and env defined in the same file.
PS: I know one of the ways is to change {{ site.url }} to {{ site.config[site.env].url }} in all the files. That should probably work.
I just want to know how to use variables in _config.yml. Is that even possible ?
No you cannot use variables in a _config file.
You can find more informations here : Change site.url to localhost during jekyll local development
Yes you can with Jekyll 3.8.0 or later version now. Please give that a try