I have to do a POST request with ansible.
My hosts.ini file is:
[workers]
worker1 ansible_host=111.111.111.111
worker2 ansible_host=222.222.222.222
The url I have to connect to needs the ip address of worker1, so I wrote my playbook as:
- hosts: worker1
tasks:
- name: inizialize worker
uri:
url: "http://{{ worker1 }}:8080/xxx/yyy"
method: POST
user: admin
password: password
force_basic_auth: yes
return_content: yes
body: "field=myfield"
But running it, I get:
the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'worker1' is undefined
Where is the problem?
You don't have a variable named worker1 defined.
If you wanted to replace the value with 111.111.111.111, you should use magic variables:
url: "http://{{ hostvars['worker1']['ansible_host'] }}:8080/xxx/yyy"
but considering your whole play, you might as well wanted:
url: "http://{{ ansible_host }}:8080/xxx/yyy"
Mind that your inventory file defines a host group named workers and your play refers to a host group named worker1 -- this makes no sense altogether.
Related
When ubuntu is installed by default, the hostname is just whatever is input into the installer.
How can I check that hostname, and append it to be a FQDN if it is not already a FQDN?
Example pseudo-yaml
- name: Set FQDN LAN hostname
hostname: "{{ current_hostname }}.lan.example.com"
when: <hostname does not end with .lan.example.com>
I take that you are looking for a condition to be matched in when:. You can use the ansible_fqdn magic (fact) variable.
Example:
- hostname:
name: "{{ ansible_hostname }}.lan.example.com"
when: ( 'lan.example' not in ansible_fqdn )
Module hostname is idempotent
There is no reason to use the condition in this task. The module will either change the hostname if it is different or keep it unchanged if it is already set. For example
- name: Set FQDN LAN hostname
hostname:
name: srv.lan.example.com
Variable ansible_hostname
This variable always keeps the name of the host. It's possible to use it to make sure the hostname is FQDN. For example
- name: Set FQDN LAN hostname
hostname:
name: "{{ ansible_hostname }}.lan.example.com"
Hi let's say I have a playbook as following
tasks:
name: get json from api
uri:
url: http://return-host-info-json.com
register: host_info
roles:
- role: hostname
I need to process this host_info and use it in other roles
How can I assign this host_info to another variable so that I can pass it to hostname role and other roles if required?
I'm new to ansible but trying to progress and learn.
I'm running a number of API calls to configure a web proxy tool.
The flow is essentially, make a GET request to see if the object exists, if does not exist, follow up with a POST request to create the object. Pretty standard.
This procedure repeats itself multiple times as the product can have a number of instances of the same type of configuration. So I would like to make the GET/POST routine as generic repeatable as possible, by associating an id.
The playbook is:
set_fact:
'vh_task_id': 01
- name: check virtual host exists
uri:
method: GET
url: "{{ admin_api_url }}/hosts?vHost={{ public_virtual_host|urlencode() }}"
return_content: yes
headers:
X-XSRF-Header: "Access"
user: "{{ admin_user }}"
password: "{{ admin_password }}"
status_code: 200
validate_certs: no
register: response
- name: set fact virtual host task id response '{{ public_virtual_host }}'
set_fact:
'response_{{ vh_task_id }}': "{{ response }}"
This all works fine, up to this point and response_{{ vh_task_id }} correctly contains the response body from the above set_fact, as I can see it, if I output it.
The issue now becomes when I want to query the JSON in response_{{ vh_task_id }} as the variable to query to get the id value.
The set_fact, is setting a literal value ofresponse_01 rather than seeing the concatenation as a registered variable.
Here is an example of how I was trying to do it:
set_fact:
'vh_id': "{{ hostvars[inventory_hostname].response_{{ vh_task_id }} | json_query('json.items[0].id') }}"
Many thanks for any help.
Try this:
set_fact:
'vh_id': "{{ hostvars[inventory_hostname].hostvar | json_query('json.items[0].id') }}"
vars:
hostvar: response_{{ vh_task_id }}
Also you don't need explicit quote ' for plain string as variable name. Like, you can change 'vh_id': to vh_id: if no other reason to keep the name with quotes.
Thanks for your time to come back, I tested this but, in the end, I have since learnt that using the with_items, gives me better results and it more repeatable
I have an inventory file with a list of hostnames, in playbook file I have a task calling uri module. How do I pass the list of hostnames in webservers group to url in playbook and make the uri task loop through the hostnames in inventory file?
Not sure if it is doable. Or the only way is to put the hostnames in vars file?
inventory file
[webservers]
hostname1
hostname2
playbook file
- uri:
url: http://[hostname1/hostname2]
return_content: yes
register: webpage
Try the below to iterate the hostnames in webserver group
- uri:
url: http://{{ inventory_hostname }}/
return_content: yes
when: inventory_hostname in groups['webservers']
register: webpage
here is how to iterate the uri task over the hosts of webserver group:
- name: loop of uri module over the hosts group
uri:
url: http://{{ item }}/
return_content: yes
register: webpage
with_items:
- "{{ groups['webserver'] }}"
I'm provisioning a new server via Terraform and using Ansible as the provisioner on my local system.
Terraform provisions a system on EC2, and then it runs the Ansible playbook providing the IP of the newly built system as the inventory.
I want to use Ansible to wait for the system to finish booting and prevent further tasks from being attempted up until a connection can be established. Up until this point I have been using a manual pause which is inconvenient and imprecise.
Ansible doesn't seem to do what the documentation says it will (unless I'm wrong, a very possible scenario). Here's my code:
- name: waiting for server to be alive
wait_for:
state: started
port: 22
host: "{{ ansible_ssh_host | default(inventory_hostname) }}"
delay: 10
timeout: 300
connect_timeout: 300
search_regex: OpenSSH
delegate_to: localhost
What happens in this step is that the connection doesn't wait any more than 10 seconds to make the connection, and it fails. If the server has booted and I try the playbook again, it works fine and performs as expected.
I've also tried do_until style loops which never seem to work. All examples given in documentation use shell output, and I don't see any way that it would work for non-shell modules.
I also can't seem to get any debug information if I try to register a result and print it out using the debug module.
Anyone have any suggestions as to what I'm doing wrong?
When you use delegate_to or local_action module, {{ ansible_ssh_host }} resolves to localhost, so your task is always running with the following parameter:
host: localhost
It waits for 10 seconds, checks the SSH connection to local host and proceeds (because most likely it is open).
If you use gather_facts: false (which I believe you do) you can add a set_fact task before, to store the target host name value in a variable:
- set_fact:
host_to_wait_for: "{{ ansible_ssh_host | default(inventory_hostname) }}"
and change the line to:
host: "{{ host_to_wait_for }}"
You can proof-test the variables with the following playbook:
---
- hosts: all
gather_facts: false
tasks:
- set_fact:
host_to_wait_for: "{{ ansible_ssh_host | default(inventory_hostname) }}"
- debug: msg="ansible_ssh_host={{ ansible_ssh_host }}, inventory_hostname={{ inventory_hostname }}, host_to_wait_for={{ host_to_wait_for }}"
delegate_to: localhost
Alternatively you can try to find a way to provide the IP address of the EC2 instance to Ansible as a variable and use it as a value for host: parameter. For example, you run Ansible from CLI, then pass ${aws_instance.example.public_ip} to --extra-vars argument.
As techraf indicates, your inventory lookup is actually grabbing the localhost address because of the delegation, so it's not running against the correct machine.
I think your best solution might be to have terraform pass a variable to the playbook containing the instance's IP address. Example:
terraform passes -e "new_ec2_host=<IP_ADDR>"
Ansible task:
- name: waiting for server to be alive
wait_for:
state: started
port: 22
host: "{{ new_ec2_host }}"
delay: 10
timeout: 300
connect_timeout: 300
search_regex: OpenSSH
delegate_to: localhost