ansible-collections / community.general

Ansible Community General Collection
https://galaxy.ansible.com/ui/repo/published/community/general/
GNU General Public License v3.0
815 stars 1.49k forks source link

linode inventory plugin is not using discovered ipv4 address(es) as ansible_host, and is trying to resolve linode tag name instead #2457

Closed life5ign closed 3 years ago

life5ign commented 3 years ago

Summary

The ansible linode dynamic inventory plugin is not using discovered ipv4 addresses as ansible_host, and is trying to resolve linode tag name instead. It is getting the information about linodes from linode_api4, but, when trying to run ansible or ansible-playbook on the host/group patterns, it simply tries to resolve the linode tag name, and can't (not in DNS).

Also posted: https://devops.stackexchange.com/questions/13833/ansible-linode-inventory-module-not-letting-ansible-or-ansible-playbook-use-lino

Issue Type

Bug Report

Component Name

linode

Ansible Version

$ ansible --version
ansible 2.10.7
  config file = /home/bryant/src/api_guys/ansible-deploy-vst/tag/ansible.cfg
  configured module search path = ['/home/bryant/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/bryant/.pyenv/versions/vst-ansible-deployment/lib/python3.9/site-packages/ansible
  executable location = /home/bryant/.pyenv/versions/vst-ansible-deployment/bin/ansible
  python version = 3.9.1 (default, Feb 16 2021, 14:25:16) [GCC 9.3.0]

Configuration

$ ansible-config dump --only-changed
CACHE_PLUGIN(/home/bryant/src/api_guys/ansible-deploy-vst/tag/ansible.cfg) = jsonfile
CACHE_PLUGIN_CONNECTION(/home/bryant/src/api_guys/ansible-deploy-vst/tag/ansible.cfg) = ~/.ansible/fact_cache
CACHE_PLUGIN_TIMEOUT(/home/bryant/src/api_guys/ansible-deploy-vst/tag/ansible.cfg) = 86400
DEFAULT_CALLBACK_WHITELIST(/home/bryant/src/api_guys/ansible-deploy-vst/tag/ansible.cfg) = ['ansible.posix.timer']
DEFAULT_HOST_LIST(/home/bryant/src/api_guys/ansible-deploy-vst/tag/ansible.cfg) = ['/home/bryant/src/api_guys/ansible-deploy-vst/tag/inventory']
DEFAULT_PRIVATE_KEY_FILE(/home/bryant/src/api_guys/ansible-deploy-vst/tag/ansible.cfg) = /home/bryant/.ssh/ansible_rsa_tag
DEFAULT_ROLES_PATH(/home/bryant/src/api_guys/ansible-deploy-vst/tag/ansible.cfg) = ['/home/bryant/src/api_guys/ansible-deploy-vst/roles']
DEFAULT_VAULT_PASSWORD_FILE(/home/bryant/src/api_guys/ansible-deploy-vst/tag/ansible.cfg) = /home/bryant/src/api_guys/ansible-deploy-vst/.vault_passwords
HOST_KEY_CHECKING(/home/bryant/src/api_guys/ansible-deploy-vst/tag/ansible.cfg) = False
TRANSFORM_INVALID_GROUP_CHARS(/home/bryant/src/api_guys/ansible-deploy-vst/tag/ansible.cfg) = always

OS / Environment

Ubuntu 20.04 LTS (PopOS)

Steps to Reproduce

Inventory plugin file:

plugin: linode
access_token: ###
regions:
  - ###
  - ###

static inventory file to group the output groups of the dynamic inventory

[nodebalancers]
newbalance ansible_host=###

[development]

[production_application_cluster]

[linode:children]
nodebalancers
development
production_application_cluster

ansible-inventory --graph linode

@linode:
  |--@development:
  |  |--linode-staging
  |--@nodebalancers:
  |  |--newbalance
  |--@production_application_cluster:
  |  |--app-2
  |  |--app-3
  |  |--app-4

and, ansible-inventory --host app-2

{
    "alerts": {
        "cpu": 250,
        "io": 10000,
        "network_in": 10,
        "network_out": 10,
        "transfer_quota": 80
    },

plus a bunch of other parameters including some hosts with one ipv4 address, some hosts with two (a public and a private). None are able to be reached by ssh by ansible.

Expected Results

I expect a host correctly identified by the linode inventory plugin to have a connection parameter ansible_host equal to its public ipv4 address (if this is how it works).

Actual Results

ansible linode -v -m ping

```bash

linode-staging | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname linode-staging: Temporary failure in name resolution",
    "unreachable": true
}
app-2 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname app-2: Temporary failure in name resolution",
    "unreachable": true
}
app-4 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname app-4: Temporary failure in name resolution",
    "unreachable": true
}
app-3 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname app-3: Temporary failure in name resolution",
    "unreachable": true
}
newbalance | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host #### port 22: Connection refused",
    "unreachable": true
}

Code of Conduct

ansibullbot commented 3 years ago

Files identified in the description:

If these files are inaccurate, please update the component name section of the description or use the !component bot command.

click here for bot help

ansibullbot commented 3 years ago

cc @Charliekenney23 @InTheCloudDan @LBGarber @decentral1se @displague @rmcintosh click here for bot help

felixfontein commented 3 years ago

I don't think this is a bug, but a design choice that doesn't fit your expectations. (Or is the behavior you expect documented?) In that case, this would be a feature (and should have an option which allows to switch to this behavior.)

life5ign commented 3 years ago

You are completely right. "Linode labels are used by default as the hostnames." https://docs.ansible.com/ansible/latest/collections/community/general/linode_inventory.html

It is by design and documented, my bad.

Also, I realized that Google sent me to an old version of the documentation, which I didn't realize, so I didn't know about the latest options.

I guess I would like to request this feature, unless the compose option above allows me to set ansible_host to the value of the public ip address, like, for example, the aws_ec2 plugin. Do you know if it does allow this?

life5ign commented 3 years ago

So with the current way it works, would I have to set my linode labels to the reverse dns values (or public ips) for each server, in order to have inventory_hostname be something that can actually be connected to by ansible (ssh in my case)? I think these dns and ips are static in linode (if they weren't this wouldn't work), but it seems a roundabout to have to do this.

life5ign commented 3 years ago

Oh wow, I can't believe this just worked:

I added

compose:
  ansible_host: 'ipv4[0]'

to my linode inventory plugin file, making a pure guess that it might grab the primary key ipv4's value, from the object returned by the ansible-inventory --host whatever_host call. It did! I think this should be added to the documentation... I still have the issue of choosing the public and not the private ip from the "ipv4" value (a list), which presents a bit of an issue, but I guess I can regex for it, since compose uses jinja filters. It could be useful to have this value be a dictionary with keys for public and private ips, so it would be easier to choose.

aminvakil commented 3 years ago

@Life5ign Thanks for adding the solution too, feel free to open a PR adding this to docs if you've found it useful for others too.

kellinm commented 3 years ago

Oh wow, I can't believe this just worked:

I added

compose:
  ansible_host: 'ipv4[0]'

to my linode inventory plugin file, making a pure guess that it might grab the primary key ipv4's value, from the object returned by the ansible-inventory --host whatever_host call. It did! I think this should be added to the documentation... I still have the issue of choosing the public and not the private ip from the "ipv4" value (a list), which presents a bit of an issue, but I guess I can regex for it, since compose uses jinja filters. It could be useful to have this value be a dictionary with keys for public and private ips, so it would be easier to choose.

I opened https://github.com/ansible-collections/community.general/pull/3203 which also includes an example for pulling the private IP address in addition to pulling in the complete information available in the upstream Linode APIv4.

This will negate the need to try and detect public vs private addresses via regex since the API provides this information already.

felixfontein commented 3 years ago

Since this is addressed by #3200, I'll close. If that's too inflexible, the solution from #3203 will allow to better handle this. (#3200 also works for already released versions.)