How to Skip hosts repository and specify host Runtime in Ansible - ansible

I do not wish to specify any hosts file to ansible-playbook command.
ansible-playbook site.yml -e "source_host=mymac1 source_file=myfile1"
My site.yml looks like this:
more site.yml
---
- hosts: "{{ source_host | default('my_pc')}}"
user: weblogic
However, I get the following error:
[WARNING]: Could not match supplied host pattern, ignoring: all
[WARNING]: provided hosts list is empty, only localhost is available
PLAYBOOK: site.yml
********************************************************************************************************************************************************************************** 2 plays in site.yml [WARNING]: Could not match supplied host pattern,
ignoring: mymac1
Can you please suggest how can i pass any host to my playbook without having to maintain and host respository with all the host information
I am on ansible version 2.3.1.0

You can use inline inventory:
playbook.yml:
- hosts: all
tasks:
- debug: msg=hello
command:
ansible-playbook -i 'mymac1,' -e source_file=myfile1 playbook.yml
note comma after hostname.
Also see: Ansible ad-hoc command with direct host specified - no hosts matched

Related

How to run ansible on specific host: ansible-playbook -i <hostname>,

The docs specify that I can run my playbook on a specific host using -i:
Patterns and ansible-playbook flags
You can change the behavior of the patterns defined in playbooks using command-line options. For example, you can run a playbook that defines hosts: all on a single host by specifying -i 127.0.0.2,. This works even if the host you target is not defined in your inventory. You can also limit the hosts you target on a particular run with the --limit flag:*
However, I tried running ansible-playbook <playbook> -i <new_hostname> -u <username> and the inventory used was still my default one. How to use this correctly?
Quoting from "man ansible"
-i, --inventory, --inventory-file
specify inventory host path or comma separated host list.
To specify a single host as a "comma separated host list", the comma is still needed. For example, the playbook
shell> cat playbook.yml
- hosts: all
gather_facts: false
tasks:
- debug:
var: inventory_hostname
gives
shell> ansible-playbook -i test_99, playbook.yml
PLAY [all] ****
TASK [debug] ****
ok: [test_99] =>
inventory_hostname: test_99
Without the comma after the host, Ansible takes the argument as an "inventory host path".
shell> ansible-playbook -i test_99 playbook.yml
[WARNING]: Unable to parse /scratch/test_99 as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit
localhost does not match 'all'
PLAY [all] ****
skipping: no hosts matched

How do I access the argument as inventory in a playbook?

I'm passing the IP as parameter as mentioned here: https://stackoverflow.com/a/18255256/1784001
ansible-playbook roles/example/main.yml -i 127.0.0.1,
Is there any way to access the value for the inventory parameter, "127.0.0.1" in a playbook?
I checked the special variables, but I see no mention of it: https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html
In some of the tasks I need that value, for example creating backup directories, or scp-ing to the host.
inventory_hostname always contains the inventory hostname of the host the play is running at.
The parameter -i "specify inventory host path or comma separated host list." Running the playbook main.yml
- hosts: all
tasks:
- debug: var=inventory_hostname
With the command
$ ansible-playbook -i 127.0.0.1, main.yml
gives
ok: [127.0.0.1] =>
inventory_hostname: 127.0.0.1

Ansible playbook run for the servers in the list

quick question for Ansible Guru's. I want to run an ansible playbook for a specific set of boxes that I copied to a list.txt disregarding the inventory and the target block in ansible playbook:
---
- name: Ansible Runbook v.1.0
hosts: test1
gather_facts: yes
# serial: "10%"
When I am running the following command I am getting no hosts matched:
ansible-playbook playbook.yaml --tags "simplejson" -vvv -i /x/home/list.txt
PLAY [Ansible Runbook v.1.0] **************************************************
skipping: no hosts matched
$cat list.txt
hostname2b
Any ideas for a workaround ?
The reason of no host matching is that host test1, which is hardcoded in playbook, is not present in the inventory file that you specified from command line. The problem is ansible-playbook command does not accept any hosts parameter. So there is no direct way of getting around the hardcoded hosts test1.
However, there is a workaround for this as explained here. You can use a variable for hosts and specify all from command line for that variable. Something like this:
---
- name: Ansible Runbook v.1.0
hosts: "{{ host_param }}"
gather_facts: yes
Then pass that variable with extra-vars:
ansible-playbook playbook.yaml -i /x/home/list.txt --extra-vars="host_param=all" --tags "simplejson" -vvv

Override hosts variable of Ansible playbook from the command line

This is a fragment of a playbook that I'm using (server.yml):
- name: Determine Remote User
hosts: web
gather_facts: false
roles:
- { role: remote-user, tags: [remote-user, always] }
My hosts file has different groups of servers, e.g.
[web]
x.x.x.x
[droplets]
x.x.x.x
Now I want to execute ansible-playbook -i hosts/<env> server.yml and override hosts: web from server.yml to run this playbook for [droplets].
Can I just override as a one time off thing, without editing server.yml directly?
Thanks.
I don't think Ansible provides this feature, which it should. Here's something that you can do:
hosts: "{{ variable_host | default('web') }}"
and you can pass variable_host from either command-line or from a vars file, e.g.:
ansible-playbook server.yml --extra-vars "variable_host=newtarget(s)"
For anyone who might come looking for the solution.
Play Book
- hosts: '{{ host }}'
tasks:
- debug: msg="Host is {{ ansible_fqdn }}"
Inventory
[web]
x.x.x.x
[droplets]
x.x.x.x
Command: ansible-playbook deplyment.yml -i hosts --extra-vars "host=droplets"
So you can specify the group name in the extra-vars
We use a simple fail task to force the user to specify the Ansible limit option, so that we don't execute on all hosts by default/accident.
The easiest way I found is this:
---
- name: Force limit
# 'all' is okay here, because the fail task will force the user to specify a limit on the command line, using -l or --limit
hosts: 'all'
tasks:
- name: checking limit arg
fail:
msg: "you must use -l or --limit - when you really want to use all hosts, use -l 'all'"
when: ansible_limit is not defined
run_once: true
Now we must use the -l (= --limit option) when we run the playbook, e.g.
ansible-playbook playbook.yml -l www.example.com
Limit option docs:
Limit to one or more hosts This is required when one wants to run a
playbook against a host group, but only against one or more members of
that group.
Limit to one host
ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit "host1"
Limit to multiple hosts
ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit "host1,host2"
Negated limit.
NOTE: Single quotes MUST be used to prevent bash
interpolation.
ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit 'all:!host1'
Limit to host group
ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit 'group1'
This is a bit late, but I think you could use the --limit or -l command to limit the pattern to more specific hosts. (version 2.3.2.0)
You could have
- hosts: all (or group)
tasks:
- some_task
and then ansible-playbook playbook.yml -l some_more_strict_host_or_pattern
and use the --list-hosts flag to see on which hosts this configuration would be applied.
An other solution is to use the special variable ansible_limit which is the contents of the --limit CLI option for the current execution of Ansible.
- hosts: "{{ ansible_limit | default(omit) }}"
If the --limit option is omitted, then Ansible issues a warning, but does nothing since no host matched.
[WARNING]: Could not match supplied host pattern, ignoring: None
PLAY ****************************************************************
skipping: no hosts matched
I'm using another approach that doesn't need any inventory and works with this simple command:
ansible-playbook site.yml -e working_host=myhost
To perform that, you need a playbook with two plays:
first play runs on localhost and add a host (from given variable) in a known group in inmemory inventory
second play runs on this known group
A working example (copy it and runs it with previous command):
- hosts: localhost
connection: local
tasks:
- add_host:
name: "{{ working_host }}"
groups: working_group
changed_when: false
- hosts: working_group
gather_facts: false
tasks:
- debug:
msg: "I'm on {{ ansible_host }}"
I'm using ansible 2.4.3 and 2.3.3
I changed mine to default to no host and have a check to catch it. That way the user or cron is forced to provide a single host or group etc. I like the logic from the comment from #wallydrag. The empty_group contains no hosts in the inventory.
- hosts: "{{ variable_host | default('empty_group') }}"
Then add the check in tasks:
tasks:
- name: Fail script if required variable_host parameter is missing
fail:
msg: "You have to add the --extra-vars='variable_host='"
when: (variable_host is not defined) or (variable_host == "")
Just came across this googling for a solution. Actually, there is one in Ansible 2.5. You can specify your inventory file with --inventory, like this: ansible --inventory configs/hosts --list-hosts all
If you want to run a task that's associated with a host, but on different host, you should try delegate_to.
In your case, you should delegate to your localhost (ansible master) and calling ansible-playbook command
I am using ansible 2.5 (2.5.3 exactly), and it seems that the vars file is loaded before the hosts param is executed. So you can set the host in a vars.yml file and just write hosts: {{ host_var }} in your playbook
For example, in my playbook.yml:
---
- hosts: "{{ host_name }}"
become: yes
vars_files:
- vars/project.yml
tasks:
...
And inside vars/project.yml:
---
# general
host_name: your-fancy-host-name
Here's a cool solution I came up to safely specify hosts via the --limit option. In this example, the play will end if the playbook was executed without any hosts specified via the --limit option.
This was tested on Ansible version 2.7.10
---
- name: Playbook will fail if hosts not specified via --limit option.
# Hosts must be set via limit.
hosts: "{{ play_hosts }}"
connection: local
gather_facts: false
tasks:
- set_fact:
inventory_hosts: []
- set_fact:
inventory_hosts: "{{inventory_hosts + [item]}}"
with_items: "{{hostvars.keys()|list}}"
- meta: end_play
when: "(play_hosts|length) == (inventory_hosts|length)"
- debug:
msg: "About to execute tasks/roles for {{inventory_hostname}}"
This worked for me as I am using Azure devops to deploy an application using CICD pipelines. I had to make this hosts (in yml file) more dynamic so in release pipeline I can add it's value, for example:
--extra-vars "host=$(target_host)"
pipeline_variable
My ansible playbook looks like this
- name: Apply configuration to test nodes
hosts: '{{ host }}'

ansible-playbook --extra-vars host array or single host

Can you pass a json array: --extra-vars "{server: [bo-121.q.net,mer-122.q.net,mer-123.q.net]}" to the host var? I want the playbook to work for one or many hosts.
It is my first boot tasks that runs on all hosts.
playbook yml:
- hosts: "$server"
If I understood the question correctly I think you can accomplish this by giving host names or groups as command line. E.g. if I want to deploy the staging server only:
ansible-playbook -i hosts.ini playbook.yml --limit staging
hosts.ini is
[default]
staging ansible_ssh_host=x.x.x.x ansible_ssh_user=x
ansible-playbook mesos.yml --extra-vars "cluster=mesos1"
mesos.yml
- hosts: '{{ cluster }}'
group / host needs to be in your inventory file.

Resources