简体   繁体   中英

Is there a way to sort the groups in an ansible host file without sorting the hosts within the groups?

In an ansible host(or inventory) file, you can group host using brackets. I want to sort these groups using sort function in linux but it will sort the individual hosts, and I want the right host to still be under the correct group. For example,

[webservers]
examplehostserver
hostname3

[database]
db_server_1
local_db_server

[ExampleGroup]
Server05
Myserver01

I'm looking for a way to sort by group while keeping the host under the correct group

I have a feeling this is not possible within terminal commands or bash

Simple bash script

#!/bin/bash
hosts_file=$1
sections=$(cat $hosts_file | grep "\[" | tr -d "[]" | sort)
for i in $sections; do
    sed -n -e "/\[$i\]/,/\[/p" $hosts_file | sed '${/\[.*/d}'
done

with larsks' input gives

[database]
db_server_1
local_db_server

[ExampleGroup]
Server05
Myserver01

[webservers]
examplehostserver ansible_host=10.0.0.1
hostname3

[webservers:vars]
apache_package_name=httpd

Native Ansible solution is limited to the groups and hosts. The play below with the example inventory from the question

tasks:
  - debug:
      msg: "{{ item }}:{{ groups[item] }}"
    loop: "{{ groups.keys()|difference(['all', 'ungrouped'])|sort }}"

gives (abridged):

"msg": "database:[u'db_server_1', u'local_db_server']"
"msg": "ExampleGroup:[u'Server05', u'Myserver01']"
"msg": "webservers:[u'examplehostserver', u'hostname3']"

and the same loop with blockinfile

tasks:
  - blockinfile:
      create: yes
      path: "{{ playbook_dir }}/my_hosts"
      block: |
             [{{ item }}]
             {% for host in groups[item] %}
             {{ host }}
             {% endfor %}
      marker: "# {mark} group:{{ item }}"
    loop: "{{ groups.keys()|difference(['all', 'ungrouped'])|sort }}"

creates file:

> cat my_hosts
# BEGIN group:database
[database]
db_server_1
local_db_server
# END group:database
# BEGIN group:ExampleGroup
[ExampleGroup]
Server05
Myserver01
# END group:ExampleGroup
# BEGIN group:webservers
[webservers]
examplehostserver
hostname3
# END group:webservers

Reconstruction of the inventory from the Ansible variables that would comprise a declaration of variables would not be unambiguous.

You could do it with a simple Python script:

#!/usr/bin/python

import sys


groups = {}
group = None
for line in sys.stdin:
    line = line.rstrip()

    if line.startswith('['):          # look for inventory groups
        group = line[1:-1].lower()    # extract the group name
        groups[group] = []

    if group and line:                # gather up non-blank lines
        groups[group].append(line)

for group in sorted(groups):          # sort groups by name
    print('\n'.join(groups[group]))   # print out the group
    print()

Assuming that we have your example inventory in the file hosts , and the above script in sortinv.py , the following command:

python sortinv.py < hosts

Produces:

[database]
db_server_1
local_db_server

[ExampleGroup]
Server05
Myserver01

[webservers]
examplehostserver
hostname3

The advantage of this mechanism is that it will preserve things like host variables and group variables. For example, given this input:

[webservers]
examplehostserver ansible_host=10.0.0.1
hostname3

[database]
db_server_1
local_db_server

[ExampleGroup]
Server05
Myserver01

[webservers:vars]
apache_package_name=httpd

We get:

[database]
db_server_1
local_db_server

[ExampleGroup]
Server05
Myserver01

[webservers]
examplehostserver ansible_host=10.0.0.1
hostname3

[webservers:vars]
apache_package_name=httpd

Much of that additional data would be lost by Vladimir's solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM