How can I pass foreman host parameters to ansible vars with foreman inventory plugin?

862 Views Asked by At

I'm trying to run Ansible playbooks without starting the execution from foreman/satellite, for many reasons (ugly scheduling is one). Instead, I want to use GitLab CI.

For this, I'm using the foreman inventory plugin, (theforeman.foreman.foreman) which allow Ansible to get inventory from foreman/satellite.

Now, my roles are using variables defined in foreman/satellite as host parameters and I don't find the way to access those from my playbook using the foreman inventory.

I have these settings in my inventory plugin yaml config:

plugin: theforeman.foreman.foreman
url: https://whatever.url...
user: rhs_inventory_reader
password: **********
host_filters: 'last_checkin > "12 hours ago" and hypervisor = false'
want_facts: true
want_hostcollections: true
want_params: true
legacy_hostvars: true

According to the documentation, parameter legacy_hostvars does this:

Places hostvars in a dictionary with keys foreman, foreman_facts, and foreman_params

I've tried to print the vars but they're not even defined in Ansible:

  tasks:
    - debug:
        var: foreman

What is wrong with this approach and how can I gather foreman host parameters from Ansible with foreman inventory, without triggering the run from within foreman?

1

There are 1 best solutions below

0
Francisco Portero On

As far as I understood using theforeman.foreman plugin inventory you need to use ansible-inventory to retrieve the data you want.

We have our foreman.yml config like below:

plugin: theforeman.foreman.foreman
url: https://satserver.this.org
user: inventory
password: XXXX
validate_certs: yes
use_reports_api: yes
legacy_hostvars: yes
want_params: yes
group: { Project_Number }

You can call to get foreman data from a specific host by:

/usr/bin/ansible-inventory -i /usr/share/ansible/plugins/inventory/theforeman.yml --host "<hostprofile>"

and you will get info like below:

{
"foreman": {
    "architecture_id": 1,
    "architecture_name": "x86_64",
    "build": false,
    "capabilities": [
        "build"
    ],
    "certname": "<hostprofile>",
    "comment": null,
...
"foreman_params": {
    "Company": "yourcompany",
    "DNS1": xx.xx.xx.xx
    "DNS2": xx.xx.xx.xy,
    "disable-firewall": "true",

The limitation using this plugin I cannot find yet the way to integrate in ansible.cfg and it seems the plugin cannot build specific Groups based on foreman_params.

The advantage is that the json data is taken directly from foreman database whenever you run the command.

However, there's another method which might help.

We don't use a plugin method as dynamic inventory, we use a adhoc python script who create a copy of foreman json data:

ansible.cfg looks like below:

gathering = smart
gather_facts = yes
fact_caching = jsonfile
inventory = /project/automati0/playbooks/this_company/customers/customerX/playbooks/dynamic_inventory
fact_caching_connection = /var/tmp/ansible/fact_cache
...

Inside /project/automati0/playbooks/dxc_lux/customers/Caceis/playbooks/dynamic_inventory you will have two files:

-rwxr-xr-- 1 root root 14653 Jun  5  2017 dynamic_inventory/foreman_ansible_inventory.py
-rw-r--r-- 1 root root  1720 Dec  2  2021 dynamic_inventory/foreman.ini

The foreman.ini file would look as foreman.yml plugin:

[foreman]
url = https://satserver.this.org
user = inventory
 
password = F7Ja2KKgUzWY6QDy9aJu
 
ssl_verify = True


# Retrieve only hosts from the organization "Web Engineering".
 # host_filters = organization="Web Engineering"

# Retrieve only hosts from the organization "Web Engineering" that are
# also in the host collection "Apache Servers".
#host_filters = name !~ "virt-who"

[ansible]
#group_patterns = ["{app}-{tier}-{color}",
#                 "{app}-{color}",
#                 "{app}",
#                 "{tier}"]

group_patterns = [
                "{Company}",
                "{customer}",
                "{Project_Number}",
                "{Business_App}",
                "{Project_Number}_{Server_App}",
                "{Project_Number}_{env}",
                "{Cmdb_Core}_{Cmdb_Env}",
                "{Business_App}_{Business_Use}",
              "{Server_App}_{Server_Function}",
              "{Server_App}_{Server_Function}"
               ]

group_prefix = sat_

# Whether to fetch facts from Foreman and store them on the host

want_facts = True



# Whether to create Ansible groups for host collections. Only tested

# with Katello (Red Hat Satellite). Disabled by default to not break

# the script for stand-alone Foreman.

want_hostcollections = True

# Whether to interpret global parameters value as JSON (if possible, else
# take as is). Only tested with Katello (Red Hat Satellite).
# This allows to define lists and dictionaries (and more complicated structures)

# variables by entering them as JSON string in Foreman parameters.
# Disabled by default as the change would else not be backward compatible.
rich_params = True

[cache]
path = /var/tmp/
filename = youcompany_satellite_ansible_inventory   
max_age = 7200
# Whether to scan foreman to add recently created hosts in inventory cache
scan_new_hosts = True
 

So, the python script will create an json inventory retrieved from foreman based on foreman.ini settings.

The advantage this method is that you can create Ansible Groups based on Foreman Params, which will give you an incredible flexibility for fulfilling vars based on Groups....

The disadvantage is that you need to run periodically ( or manually ) if you want to see latest change within foreman.