gather facts from multiple groups?

Hi,
Its been a while since I have posted, which is really a compliment to
all the awesome modules. We have signifcan number of our projects
covered by ansible.

Has anyone seen an issue gathering facts and getting Authentication failed?

We have playbooks that start like this:

- hosts: citrusleaf200
  user: jmarcus
  sudo: False
  gather_facts: True

- hosts: citrusleaf000
  sudo: False
  gather_facts: True

- hosts: citrusleaf506.domain.net
  user: root
  sudo: False
  gather_facts: True

We run the playbook like this: ansible-playbook citrusleaf.yml -k

and when turning verbose on we get:

fatal: [citrusleaf204.domain.net] => {'msg': 'FAILED: Authentication
failed.', 'failed': True}
fatal: [citrusleaf202.domain.net] => {'msg': 'FAILED: Authentication
failed.', 'failed': True}
fatal: [citrusleaf203.domain.net] => {'msg': 'FAILED: Authentication
failed.', 'failed': True}
fatal: [citrusleaf205.domain.net] => {'msg': 'FAILED: Authentication
failed.', 'failed': True}
<citrusleaf206.domain.net> ESTABLISH CONNECTION FOR USER: jmarcus on
PORT 22 TO citrusleaf206.domain.net
<citrusleaf208.domain.net> ESTABLISH CONNECTION FOR USER: jmarcus on
PORT 22 TO citrusleaf208.domain.net
<citrusleaf207.domain.net> ESTABLISH CONNECTION FOR USER: jmarcus on
PORT 22 TO citrusleaf207.domain.net
<citrusleaf209.domain.net> ESTABLISH CONNECTION FOR USER: jmarcus on
PORT 22 TO citrusleaf209.domain.net
fatal: [citrusleaf201.domain.net] => {'msg': 'FAILED: Authentication
failed.', 'failed': True}
<citrusleaf210.domain.net> ESTABLISH CONNECTION FOR USER: jmarcus on
PORT 22 TO citrusleaf210.domain.net
fatal: [citrusleaf206.domain.net] => {'msg': 'FAILED: Authentication
failed.', 'failed': True}
fatal: [citrusleaf207.domain.net] => {'msg': 'FAILED: Authentication
failed.', 'failed': True}
fatal: [citrusleaf208.domain.net] => {'msg': 'FAILED: Authentication
failed.', 'failed': True}
<citrusleaf212.domain.net> ESTABLISH CONNECTION FOR USER: jmarcus on
PORT 22 TO citrusleaf212.domain.net
<citrusleaf211.domain.net> ESTABLISH CONNECTION FOR USER: jmarcus on
PORT 22 TO citrusleaf211.domain.net
fatal: [citrusleaf210.domain.net] => {'msg': 'FAILED: Authentication
failed.', 'failed': True}
fatal: [citrusleaf209.domain.net] => {'msg': 'FAILED: Authentication
failed.', 'failed': True}
fatal: [citrusleaf212.domain.net] => {'msg': 'FAILED: Authentication
failed.', 'failed': True}
fatal: [citrusleaf211.domain.net] => {'msg': 'FAILED: Authentication
failed.', 'failed': True}

I have tried removing the jmarcus user so that it uses default but it
doesn't make a difference.

Is this a known issue?

ansible 1.1

Thanks,
James

Sounds like these are general auth issues not so much a fact gathering specific thing.

Try running your playbook with -v -v -v and see how it is logging in and then see what you get.

Then try to SSH in with the same way and let me know what you find out.

BTW, this is unrelated, but you can do this:

  • hosts: group1:group2
    sudo: False
    gather_facts: True

This means group1 or group2

You can also say stuff like

group1:group2:&group3

Which means (group1 or group2) and MUST BE in group3

and

group1:group2:!group3

Which means (group1 or group2) and absolutely not in group3

Oh, wow. This is amazing. Now if it could also be combined with variables, that would be awesome.

Example:

  • hosts: {{myhosts}}:&group2

This would mean that I call a PlayBook with the extra var of myhosts and the play only gets executed for hosts that are in myhosts AND ALSO in group2.

But it looks as if I couldn’t get this to work. Is that a bug or a limitation?

Hosts get loaded before some other things, but you can pass variables in with -e in this case.

ansible-playbook foo.yml -e “myhosts=webservers”

or

-e “myhosts=acme1.example.com:acme2.example.com

etc

Yes, I know. And that’s exactly what I want to utilize but which doesn’t seem to be working.

Let’s call this:

ansible-playbook foo.yml -e “myhosts=host17”

And the foo.yml would look like this:

  • hosts: {{myhosts}}:&dbserver
    tasks: [some tasks]

  • hosts: {{myhosts}}:&webserver
    tasks: [some other tasks]

Which would execute [some tasks] if host17 is member of dbserver and it would execute [some other tasks] if host17 is member of webserver. But that doesn’t work. It looks like when we use

  • hosts: {{myhosts}}

then the variable {{myhosts}} gets resolved but when using

  • hosts: {{myhosts}}:&group

then the variable does NOT get resolved.

I’m not sure you are really seeing a “resolution” error or if you are seeing a syntax error.

If you start a YAML entry with “{” it will think it is likely a hash, so you have to quote it.

  • hosts: {{myhosts}}:&group

becomes

  • hosts: “{{myhosts}}:&group”

Perfect, that’s exactly what I was looking for :slight_smile:

To be honest, I’m often struggling with the right syntax with regard to variables. Is there an overview available that explains the correct synatx in all different context?

There’s really not such a thing as different contexts in 1.2 – playbooks and templates use {{ foo }} for variable interpolation equally, which is one of the very nice things about 1.2.

This is just a YAML syntax thing where you need to quote the line value.

There are a couple of special cases where YAML will try to ‘interpret’ the data strings used by ansible and require a work-around. I was thinking of adding a “Gotcha’s” section at the end of the YAML documentation to cover these. If this is desired, I’ll see if I can get a pull request together today.

K

I was just thinking this too.

It should definitely discuss the two following things:

foo: {{ splat }}

Should be

foo: “{{ splat }}”

And also

foo: bar msg=glorp:gluzz

Should be

foo: bar msg=“glorp:gluzz”

If a line contains a colon or starts with a “{”, quote the whole line.

I have long thought about making Ansible detect this on the fly and make it work via magic, so the question does not arise, but in doing so, we make the file not be YAML anymore, which is something I believe we shouldn’t do as true “infrastructure as data” is important to me.

Thankfully, it’s just those two gotchas that I know of.

There’s two other gotchas that I know of.

Expressions involving quoted strings:

when: foo == “bar”

works, but

when: “bar” == foo

doesn’t because YAML things the leading " signals the start of a string value, and you have to do

when: ‘“bar” == foo’

or

when: >

“bar” == foo

to get around it.

A colon followed by a space:

lineinfile: dest=/etc/sudoers state=present regexp=“^%wheel” line=“%wheel ALL=(ALL) NOPASSWD: ALL”

Won’t work in a playbook, even though the argument does work on ‘ansible -m lineinfile’ command line,because of the ‘NOPASSWD: ALL’ You have to use the special YAML ‘>’ quoting trick to get around it:

lineinfile: >
dest=/etc/sudoers
state=present
regexp=“^%wheel”
line=“%wheel ALL=(ALL) NOPASSWD: ALL”

As an aside, I agree that its probably not a good idea to make ansible do any magic preprocessing here. Introducing exceptions can make it harder to track down syntax errors if you don’t know all the rules that are in play (i.e. is it an YAML error, or an Ansible key-value error or a Jinja2 error). That’s one reason why I don’t like new magic continuation lines: playbooks that use them are technically not valid YAML and the existing YAML ‘>’ quoting mechanism does the same thing explicitly with just a single character added. Then again, its mostly harmless and I’m just being pedantic :slight_smile:

K

Here is another one:

Using this

  • name: Something
    subversion: repo=‘svn path’
    dest=‘/var/www/{{ item }}/htdocs’
    with_items: $groups[‘webserver’]

does work. However, using

  • include other.yml host={{ item }}
    with_items: $groups[‘webserver’]

does NOT work, it complains that with_items requires a list.

So, is my notation completely wrong? But it works in the first case. Or is there something wrong with the include directive?

So the “colon followed by a space” is the SAME thing as “if line contains colon”.

We need to be careful here about making this section too confusing and just having a few simple rules. I’ll take care of it.

BTW, include + with_items is basically unsupported. There’s a reason we don’t use it in the documentation anymore.

Sorry Michael, don’t want to upset you, just looking for clarity.

The include + with_items must have been removed in the last 24 hours as I just found it there yesterday. But if it’s unsupported I will of course try and find a different approach. Any suggestions on how else I could achieve nested loops in playbooks then?

Your statement about colons isn’t quite clear, I’m afraid. Do you mean I should quote like “with_items: $group[‘webserver’]”? But why is it working in the other case with exactly the same line including a colon?

Not upset, should have used italics instead of all caps :slight_smile:

Yeah, I meant a second colon on the same line, basically.

Dammit! Gmail wont let me reply to this group directly anymore. Have to use the Groups interface.

Ok, so "line contains a colon followed by a space is the criteria, not the other. Got it.

Still basically two criteria, not three, so that’s good too :slight_smile:

Just had a peak at the the new Gotchas section on the site. The workaround suggested might be a bit confusing for anyone who does not understand how YAML quoting works – which I think is the real gotcha.

Try running the following playbook:

  • hosts: localhost
    connection: local
    tasks:
  • debug: msg=“foo: bar”

A newbie might think the ': ’ has been quoted when it hasn’t. Even more confusing if they are using the command, shell or lineinfile modules and are trying to get their head around how/if their ‘quotes’ propagate. The first non-space character after the ': ’ sequence largely determines how the rest of the line/block is interpreted.

Yuck. I’ve been thinking about this for a solid 10 minutes and can’t come up with a sufficiently simple way of explaining YAML string values.

K

It’s not that bad, I’ll look at modifying the text a little.