Ansible group vars on specific host - ansible

I try to push specific conf with group_vars, but it only make push for one instance aa.yml and I don't have the push for bb.yml inventory. I already used group_vars and works before, but not with conf ansible
- name: Push conf
uri:
url: "https://xxx{{ instance_id }}"
method: POST
status_code: [201]
headers:
Content-Type: application/json
body_format: json
body: "{\"server\":{{ server }},\"labels\":{{{ site }}},\"name\":\"{{ instance.value.name }}"
return_content: true
vars:
instance: "{{ item }}"
loop: "{{ instances }}"
inventory/host/group_vars/aa/aa.yml
site: "\"aa\""
instance_id: "06a56590"
server: "[\"server1\"]"
inventory/host/group_vars/bb/bb.yml
site: "\"bb\""
instance_id: "bcc37660"
server: "[\"server2\"]"
inventory/host/000_hosts
[host]
server1
server2
The command:
ansible-playbook task.yml -i inventory/host/000_hosts --extra-vars "target=host"

Supplying with an answer:
group_vars/XXX directories typically refers to groups defined in your inventory, and they contain variables only available for that group. In your case you created directories for the groups aa and bb, these groups does not exists in your inventory, meaning when you call your playbook referring to your hosts (- hosts: host), ansible will look for group variables related to that group. Which is this case does not exists.
As you will see in my suggestion below; by using the keyword children in your inventory, you are basically saying: The hosts defined in the group aa/bb is part/children of the group host (the parent), and the variables follows. (inheriting-variable-values-group-variables-for-groups-of-groups)
Changing your inventory to the following, should solve the problem:
inventory/host/hosts
[aa]
server1
[bb]
server2
[host:children]
aa
bb
You could also change your directory structure to something like:
inventory/
├── group_vars
│   ├── aa
│   │   └── aa.yml
│   └── bb
│   └── bb.yml
└── hosts
Edit:
However, if I'm not mistaken: your hosts directory (in inventory/hosts) is typically used to identify your environment like:
Multistage environment Ansible
.
├── ansible.cfg
├── environments/ # Parent directory for our environment-specific directories
│ │
│ ├── dev/ # Contains all files specific to the dev environment
│ │ ├── group_vars/ # dev specific group_vars files
│ │ │ ├── all
│ │ │ ├── db
│ │ │ └── web
│ │ └── hosts # Contains only the hosts in the dev environment
│ │
│ ├── prod/ # Contains all files specific to the prod environment
│ │ ├── group_vars/ # prod specific group_vars files
│ │ │ ├── all
│ │ │ ├── db
│ │ │ └── web
│ │ └── hosts # Contains only the hosts in the prod environment
│ │
│ └── stage/ # Contains all files specific to the stage environment
│ ├── group_vars/ # stage specific group_vars files
│ │ ├── all
│ │ ├── db
│ │ └── web
│ └── hosts # Contains only the hosts in the stage environment
│
├── playbook.yml
│
└── . . .
Take a look at organizing-host-and-group-variables

Related

Ansible, is group_vars and host_vars dirs at multiple levels supported?

I am experimenting with variable overriding in Ansible. To do so, I have created the below-depicted directory structure. Note that under inventories, I have created two separate sites (1 & 2)
Also, note that I have added group_vars/host_vars at two different levels; below inventories and each site.
.
├── ansible.cfg
├── inventories
│ ├── group_vars
│ │ └── all.yml
│ ├── host_vars
│ │ └── target2.yml
│ ├── site1
│ │ ├── group_vars
│ │ │ └── all.yml
│ │ ├── host_vars
│ │ │ └── target1.yml
│ │ └── hosts.yml
│ └── site2
│ ├── group_vars
│ │ └── all.yml
│ ├── host_vars
│ │ └── target2.yml
│ └── hosts.yml
├── modules
├── playbooks
│ └── playbook1
│ ├── group_vars
│ │ └── all.yml
│ └── host_vars
└── roles
I would like to be able to store default variables for groups/hosts at "inventories" level and override them when/if necessary at site/group/host level using directories (not the hosts.yml), but I am unable to do so.
If I test the inventory by targeting the base "inventories" directory, I can see that group_vars/host_var folders under sites are ignored:
ansible-inventory --vars --graph -i inventories/
#all:
|--#site1:
| |--target1
| | |--{scope = inventories/site1/hosts.yml}
| |--target2
| | |--{scope = inventories/host_vars/target2.yml}
|--#site2:
| |--target2
| | |--{scope = inventories/host_vars/target2.yml}
|--#ungrouped:
|--{scope = inventories/group_vars/all.yml}
But if I target a specific site, the underlying group_vars/host_var folder are used, but of course the one at base "inventory" are ignored:
ansible-inventory --vars --graph -i inventories/site1
#all:
|--#site1:
| |--target1
| | |--{scope = inventories/site1/host_vars/target1.yml}
| |--target2
| | |--{scope = inventories/site1/group_vars/all.yml}
|--#ungrouped:
|--{scope = inventories/site1/group_vars/all.yml}
ansible-inventory --vars --graph -i inventories/site2
#all:
|--#site2:
| |--target2
| | |--{scope = inventories/site2/host_vars/target2.yml}
| |--{scope = inventories/site2/group_vars/all.yml}
|--#ungrouped:
Is it possible to instruct ansible to look for group_vars/host_var folders in the entire directory structure?
Thanks!
According your description and example your sets site1 and site2 are already subsets of set all. You made the observation and described it in your question
If I target a specific site, the underlying group_vars/host_var folder are used, but of course the one at base "inventory" are ignored
also the used command gives a hint
ansible-inventory --vars --graph -i inventories/site1 # or 2
since with this you'll set the root of a tree structure or graph to a sub tree or part of a graph.
Is it possible to instruct Ansible to look for group_vars/host_var folders in the entire directory structure?
No, since there will be not other directory outside of the defined subset, sub tree or graph part.
but of course the one at base "inventory" are ignored
In other words, the base "inventories" doesn't exists (anymore) since you've set the base to "inventories/site1" or 2.
An other approach could be to have one inventory for each site.

Ansible - variable for a specific inventory

I have a multi environment & multi inventories setup within ansible (2.7.9).
With one of the inventories, I am wanting to set a global variable to be inherited by all the hosts within the inventory. For this purpose I added the variable into that specific inventory (inventory/production/prodinv):
[all:vars]
myvar="True"
And it works fine if I ran ansible against that specific inventory (inventory/production/prodinv). However, if I run ansible against the inventory directory (eg inventory/production) , I noticed that the variable is inherited on all the hosts across all the inventories - which isn't ideal because I only want the hosts within firstenv inventory to have the var defined.
Currently group_vars and host_vars are a symlink (for all the inventories) against a "shared" root group_vars and host_vars.
To add more clarity to my question, below is the structure of my ansible:
.
├── ansible.cfg
├── playbooks/
├── roles/
├── inventory/
│ │
│ ├── group_vars/
| |
| ├── host_vars/
| |
│ ├── tnd/
│ │ ├── group_vars/ -> ../group_vars
│ | ├── host vars/ -> ../host_vars
│ │ └── devinv
│ │
│ ├── production/
│ │ ├── group_vars/ -> ../group_vars
│ | ├── host vars/ -> ../host_vars
│ │ └── prodinv
│
└── . .
I'm not sure how / where to define this var that should apply to all hosts/groups within a particular inventory, without running into the same issue. Ideas?
Thanks,
J
I think your problem is two-fold.
Ansible applies the group_vars of a directory to all files and subdirectories within the specified inventory directory. So, inventory/production/group_vars will get applied to everything within inventory/production. This just gets masked when you explicitly limit your inventory further while running, like you did (-i inventory/production/prodinv).
This means that you need to put the group_vars only being applied to prodinv in their own directory and not in the inventory/production directory. For example, inventory/production/prodinv/group_vars.
Your symlinks are set up in a way that if you run against inventory, you're going to have the same group_vars applied to all your inventories. You're not hitting this in your example, but you'll likely hit it in the future.

Vagrant ansible: pick var fron environment variable

Here my ansible_local related Vagrantfile code:
config.vm.provision "ansible_local" do |ansible|
ansible.become = true
ansible.inventory_path = '/vagrant/provisioning/inventory/hosts.ini'
ansible.playbook = "/vagrant/provisioning/playbook.yml"
ansible.limit = 'all'
ansible.galaxy_role_file = "/vagrant/provisioning/requirements.yml"
ansible.galaxy_roles_path = "/etc/ansible/roles"
ansible.galaxy_command = "sudo ansible-galaxy install --role-file=%{role_file} --roles-path=%{roles_path} --force"
end
As you can see, ansible.limit is all.
├── ansible.cfg
├── provisioning
│   ├── group_vars
│   │   └── all.yml
│   ├── inventory
│   │   ├── hosts.ini
│   │   └── hosts.yml
│   ├── playbook.yml
│   └── requirements.yml
└── Vagrantfile
all.yml content is:
solr_cores:
mssql_restore_backups: false
I need to replace mssql_restore_backup default value picking it up from an environment variable.
Is there anyway to pass environment variable value to ansible provisioner?
Any ideas?
In Ansible the variables with mayor precedence are extra-vars and you can add them to your Vagrantfile as below
ansible.extra_vars = {
mssql_restore_backup: $MSSQLRESTOREBACKUP
}
Documentation:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#understanding-variable-precedence
https://www.vagrantup.com/docs/provisioning/ansible_common#extra_vars

How to add more information to Prometheus Gauge?

I want to monitor the statistics of different subprocesses that are running in pods in different namespaces with Prometheus and I am looking for a way to properly expose this information.
My cluster is similar to below:
cluster
├── ns1
│   ├── ns1-pod1
│ │ ├── proc-p1-1
│ │ └── proc-p1-2
│   └── ns1-pod2
│ ├── proc-p2-1
│ └── proc-p2-2
└── ns2
   ├── ns2-pod1
│ ├── proc-p1-1
│ └── proc-p1-2
   └── ns2-pod2
├── proc-p2-1
└── proc-p2-2
Each pod is publishing the statistics of its processes to RabbitMQ with a specific routing key and I can read the statistics from there.
I wrote an exporter that can connect to RMQ in one namespace, read the statistics and expose them on the /metrics so Prometheus can read it. An example of my exporter:
// prometheus go client
var MemoryValue = prometheus.NewGauge(
prometheus.GaugeOpts{
Namespace: namespace,
Name: "MemoryValue",
Help: "MemoryValue",
})
prometheus.MustRegister(MemoryValue)
MemoryValue.Set(opst.Memory.Value) // "opst.Memory.Value" is what I get from RMQ
The problem is I don't know how to label the metrics for each process in a pod. I mean, for example, at the moment I have 4 processes in ns1 but I am exposing all of them on MemoryValue. I need a way similar to Namespace to label each process by pod and process names (I have this information but how to add them to Prometheus?).
As #Peter correctly mentioned the solution is to use GaugeVec:
var CpuPercentValue = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: "MyExporter",
Name: "CpuPercentValue",
Help: "CpuPercentValue",
},
[]string{
"namespace",
"proc_qID",
"opID",
},
)
CpuPercentValue.With(prometheus.Labels{"namespace": namespace, "proc_qID": procid, "opID": opid}).Set(opst.CpuPercent.Value)

Passing variables to ansible roles

I have my directory structure as this
└── digitalocean
├── README.md
├── play.yml
└── roles
├── bootstrap_server
│   └── tasks
│   └── main.yml
├── create_new_user
│   └── tasks
│   └── main.yml
├── update
│   └── tasks
│   └── main.yml
└── vimserver
├── files
│   └── vimrc_server
└── tasks
└── main.yml
When I am creating a user under the role create_new_user, I was hard coding the user name as
---
- name: Creating a user named username on the specified web server.
user:
name: username
state: present
shell: /bin/bash
groups: admin
generate_ssh_key: yes
ssh_key_bits: 2048
ssh_key_file: .ssh/id_rsa
- name: Copy .ssh/id_rsa from host box to the remote box for user username
become: true
copy:
src: ~/.ssh/id_rsa.pub
dest: /home/usernmame/.ssh/authorized_keys
mode: 0600
owner: username
group: username
One way of solving this may be to create a var/main.yml and put the username there. But I wanted something through which I can specify the username at play.yml level. As I am also using the username in the role vimrcserver.
I am calling the roles using play.yml
---
- hosts: testdroplets
roles:
- update
- bootstrap_server
- create_new_user
- vimserver
Would a template work here in this case? Couldn't find much from these SO questions
I got it working by doing a
---
- hosts: testdroplets
roles:
- update
- bootstrap_server
- role: create_new_user
username: username
- role: vimserver
username: username
on play.yml
Although would love to see a different approach then this
Docs: http://docs.ansible.com/ansible/playbooks_roles.html#roles
EDIT
I finally settled with a directory structure like
$ tree
.
├── README.md
├── ansible.cfg
├── play.yml
└── roles
├── bootstrap_server
│   └── tasks
│   └── main.yml
├── create_new_user
│   ├── defaults
│   │   └── main.yml
│   └── tasks
│   └── main.yml
├── update
│   └── tasks
│   └── main.yml
└── vimserver
├── defaults
│   └── main.yml
├── files
│   └── vimrc_server
└── tasks
└── main.yml
Where I am creating a defaults/main.yml file inside the roles where I need the usage of {{username}}
If someone is interested in the code,
https://github.com/tasdikrahman/ansible-bootstrap-server
You should be able to put username in a vars entry in play.yml.
Variables can also be split out into separate files.
Here is an example which shows both options:
- hosts: all
vars:
favcolor: blue
vars_files:
- /vars/external_vars.yml
tasks:
- name: this is just a placeholder
command: /bin/echo foo
https://docs.ansible.com/ansible/playbooks_variables.html#variable-file-separation
Ansible seems to delight in having different ways to do the same thing, without having either a nice comprehensive reference, or a rationale discussing the full implications of each different approach :). If you didn't remember the above was possible (I'd completely forgotten vars_files), the easiest option to find from the documentation might have been a third way, which is the most sophisticated one.
There's a prominent recommendation for ansible-examples. You can see a group_vars directory, with files which automatically provide values for hosts according to their groups, including the magic all group. The group_vars directory can be placed in the same directory as the playbook.
https://github.com/ansible/ansible-examples/tree/master/lamp_simple
Maybe this is what you want?
---
- hosts: testdroplets
roles:
- update
- bootstrap_server
- { role: create_new_user, username: 'foobar' }
- vimserver
https://docs.ansible.com/ansible/2.5/user_guide/playbooks_reuse_roles.html#using-roles
If you use include_role, variables can be passed like below.
- hosts: all_hosts
tasks:
- include_role:
name: "path/to/role"
vars:
var1: "var2_value"
var2: "var2_value"
Can't you just pass the variable from the command line with the -e parameter? So you can specifiy the variable even before execution. This also results in the strongest variable declaration which always takes precendence (see Variable precendence).
If you want to place it inside your playbook I suggest defining the username with the set_fact directive in the playbook. This variable is then available in all roles and included playbooks as well. Something like:
---
- hosts: testdroplets
pre_tasks:
- set_fact:
username: my_username
roles:
- update
- bootstrap_server
- create_new_user
- vimserver
It is all here: http://docs.ansible.com/ansible/playbooks_variables.html
while there are already some good answers, but I wanted to add mine because I've done this exact thing.
Here is the role I wrote: https://github.com/jmalacho/ansible-examples/tree/master/roles/users
And, I use hash_merge=true, and ansible's group_vars to make a dictionary of users: keys,groups so that adding a new user by host or by environment, and re-running is easy.
I also wrote up how my team uses group variables for environments once like this: "https://www.coveros.com/ansible-environment-design/"

Resources