Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

yaml inventory: Support host-list (not a dictionary) #22567

Closed
wants to merge 2 commits into from

Conversation

dagwieers
Copy link
Contributor

@dagwieers dagwieers commented Mar 13, 2017

SUMMARY

Currently the YAML parser expects that every hosts-entry comprises of a dictionary of hosts with variables. Unfortunately that's not the case, inventories can simply consist of a list of hosts (because variables are defined elsewhere) and this would result in:

ERROR! Attempted to read "hosts.yaml" as YAML: list indices must be integers, not AnsibleUnicode

This PR allows for listing hosts as one would expect in YAML, just as one can do in a JSON inventory.
And it also support empty values.

ISSUE TYPE
  • Feature Pull Request
COMPONENT NAME

yaml inventory

ANSIBLE VERSION

v2.3

@ansibot ansibot added affects_2.3 This issue/PR affects Ansible v2.3 c:inventory/yaml needs_triage Needs a first human triage before being processed. labels Mar 13, 2017
@bcoca bcoca removed the needs_triage Needs a first human triage before being processed. label Mar 13, 2017
@bcoca
Copy link
Member

bcoca commented Mar 13, 2017

I'm not sure what you are trying to do here, can you show examples?

@bcoca bcoca added the needs_info This issue requires further information. Please answer any outstanding questions. label Mar 13, 2017
@dagwieers
Copy link
Contributor Author

dagwieers commented Mar 13, 2017

In a YAML inventory it now expects for groups:

all:
  hosts:
    host1:
      var1: value1a
      var2: value2
    host2:
      var1: value1b
      var2: value2
windows:
  hosts:
    host1: null
    host2: null

Whereas in various cases we have, a simple list would do. (JSON supports this fine)

all:
  hosts:
    host1:
      var1: value1a
      var2: value2
    host2:
      var1: value1b
      var2: value2
windows:
  hosts:
  - host1
  - host2

In an inventory you only need to specify the host-vars for a host only once. So what we do is define the hostvars for group "all" only, and use lists (and not dictionaries) everywhere else.

@bcoca
Copy link
Member

bcoca commented Mar 13, 2017

the reason it does not use lists is to avoid duplicates

@ansibot ansibot removed the needs_info This issue requires further information. Please answer any outstanding questions. label Mar 13, 2017
@dagwieers
Copy link
Contributor Author

dagwieers commented Mar 13, 2017

The JSON inventory doesn't have this restriction.
Why don't we simply make it a set internally if this is a concern ?

Dictionaries are used for key-value pairs, we don't have key-value pairs here.
And dictionaries can also have duplicate entries, causing the last entry to overwrite prior entries silently.
So I guess also in that case proper handling/escalating will be required.

@bcoca bcoca added this to the 2.4.0 milestone Mar 13, 2017
@bcoca
Copy link
Member

bcoca commented Mar 13, 2017

I'm torn on this one, i see your point, but I also think that keeping them at keys allows users to go back n forth with vars w/o having to restructure the entries.

@dagwieers
Copy link
Contributor Author

True, I am not preventing people from doing that though. I am just supporting lists as well.

But I don't mind doing the legwork for ensuring lists are like sets. A simply existence check in add_host would be sufficient, or turning them into a set(), which is what I prefer.

(To be honest, I think there's only one place where host-vars should be defined and there's no need to move them around. That is why we defined them as part of the "all" group.)

@bcoca
Copy link
Member

bcoca commented Mar 13, 2017

people define them in diff levels, we give flexibility towards organizing them as best as it suits their environment, I would loathe forcing the 1 way.

@dagwieers
Copy link
Contributor Author

Nope, I wouldn't force anyone. it's just that picking one place to define host-vars prevents duplicate definitions of host-vars and headaches finding what's going on. Because I doubt it's obvious which host-vars win in this case (as they are processed sequentially, I'd guess the last one wins, but that's likely depending on the YAML parser).

@dagwieers
Copy link
Contributor Author

dagwieers commented Mar 13, 2017

@bcoca I updated the PR, it now reports when a list has duplicate entries:

[WARNING]: While parsing hosts list, found a duplicate entry for host 'localhost' in group 'linux'

much like how it does for duplicate keys in a dictionary.

@bcoca
Copy link
Member

bcoca commented Mar 13, 2017

dupes would have not made their way to inventory, my point was letting the YAML parser dedupe early and cheaply.

@dagwieers
Copy link
Contributor Author

I know they would not ended up in the inventory, but with dictionaries you get a warning if there are duplicate entries. Now the same will happen for duplicate entries in a list. I assumed that this was your concern. If it is not, and you prefer to get rid of this warning, I can remove it again.

I can't do this in the YAML parser, because for some lists duplicates are intended, so it should be very specific to 'hosts' dictionaries in groups.

@bcoca
Copy link
Member

bcoca commented Mar 13, 2017

you can remove the warning

@dagwieers dagwieers force-pushed the yaml-hostlist branch 2 times, most recently from acb7af7 to 97902b4 Compare March 13, 2017 19:25
@ansibot ansibot added the affects_2.4 This issue/PR affects Ansible v2.4 label Mar 23, 2017
@dagwieers dagwieers force-pushed the yaml-hostlist branch 2 times, most recently from 68a20a4 to 2066ab8 Compare April 7, 2017 09:22
@dagwieers
Copy link
Contributor Author

@bcoca I have updated my patch to the new inventory model. So this patch is to support a list of hosts rather than a dictionary of hosts as key. Especially for groups where you don't need to add host variables, you don't want to use dictionaries, especially because generated YAML lists with dictionary using empty values results in:

vmware:
  hosts:
    vmware-guest-01: null
    vmware-guest-02: null

Rather than:

vmware:
  hosts:
  - vmware-guest-01
  - vmware-guest-02

@ansibot ansibot added stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. support:core This issue/PR relates to code supported by the Ansible Engineering Team. labels Jun 24, 2017
@ansibot ansibot removed the stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. label Jul 4, 2017
@abadger
Copy link
Contributor

abadger commented Jul 11, 2017

Code looks good to me.

@abadger
Copy link
Contributor

abadger commented Jul 11, 2017

@bcoca does your last message mean that you're okay with this (it does mirror what can be done with the ini format) and just wanted the message updated?

@bcoca
Copy link
Member

bcoca commented Jul 11, 2017

No, i would still like to keep current format w/o complicating it with variations, I was also working on a schema validator for ansible-inventory, something like this for DTD:

name: Ansible YAML Inventory
type: map
mapping:
    desc: name of a group
    type: map
    unique: yes
    mapping: *group
      "hosts":
        desc: hosts that are part of this group
        type: map
        mapping:
          unique: yes
          desc: name of each host (inventory_hostname)
          type: map
          mapping:
            desc: vars associated with this host
      "children":
        type: map
        desc: child groups
        mapping: &group
      "vars":
        desc: vars associated with this group
        type: map
        mapping:
          unique: yes

@dagwieers
Copy link
Contributor Author

dagwieers commented Jul 13, 2017

So I disagree with defining host-lists as dictionary with empty values and allowing to have host-vars defined anywhere a host is added to a group in the YAML inventory:

all:
    hosts:
        host2:
            dns_server: a.b.c.d
    vars:
        dns_server: c.d.e.f
datacenter1:
    hosts:
        host2:
            dns_server: 2.3.4.5
        host3:
            dns_server: 3.4.5.6
    vars:
        dns_server: 6.7.8.9
windows:
    hosts:
        host1: null
            dns_server: 1.2.3.4
        host2: null
    vars:
        dns_server: 7.8.9.1

for the following reasons:

  • It does not make YAML convenient or human-editable (a list of hosts should just be a YAML list)
  • Having your hostvars (potentially) distributed over your complex YAML inventory is a potential support nightmare (especially if that file is managed by more than one person)

I much rather preferred a single location in the specification to add your host-vars (just like group-vars now are defined in a single location) and have lists of hosts as YAML lists.

_hostvars:
    host1:
        dns_server: 1.2.3.4
    host2:
        dns_server: 2.3.4.5
datacenter1:
    hosts:
    - host2
    - host3
windows:
    hosts:
    - host1
    - host2

IMO this is a design mistake, one we apparently can't or won't change.

@ansibot ansibot added feature This issue/PR relates to a feature request. and removed feature_pull_request labels Mar 4, 2018
@ansible ansible locked and limited conversation to collaborators Apr 26, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affects_2.3 This issue/PR affects Ansible v2.3 affects_2.4 This issue/PR affects Ansible v2.4 c:inventory/group feature This issue/PR relates to a feature request. support:core This issue/PR relates to code supported by the Ansible Engineering Team.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants