1
0
mirror of https://github.com/ansible/awx.git synced 2024-11-01 16:51:11 +03:00

Merge pull request #6595 from jangsutsr/6234_set_priority_rules_for_find_matching_hosts

Set priority rules for find_matching_hosts
This commit is contained in:
Aaron Tan 2017-06-23 14:04:18 -04:00 committed by GitHub
commit 68ee601359
3 changed files with 60 additions and 31 deletions

View File

@ -3053,40 +3053,29 @@ class JobTemplateCallback(GenericAPIView):
# Find the host objects to search for a match.
obj = self.get_object()
hosts = obj.inventory.hosts.all()
# First try for an exact match on the name.
try:
return set([hosts.get(name__in=remote_hosts)])
except (Host.DoesNotExist, Host.MultipleObjectsReturned):
pass
# Next, try matching based on name or ansible_host variables.
matches = set()
# Populate host_mappings
host_mappings = {}
for host in hosts:
for host_var in ['ansible_ssh_host', 'ansible_host']:
ansible_host = host.variables_dict.get(host_var, '')
if ansible_host in remote_hosts:
matches.add(host)
if host.name != ansible_host and host.name in remote_hosts:
matches.add(host)
host_name = host.get_effective_host_name()
host_mappings.setdefault(host_name, [])
host_mappings[host_name].append(host)
# Try finding direct match
matches = set()
for host_name in remote_hosts:
if host_name in host_mappings:
matches.update(host_mappings[host_name])
if len(matches) == 1:
return matches
# Try to resolve forward addresses for each host to find matches.
for host in hosts:
hostnames = set([host.name])
for host_var in ['ansible_ssh_host', 'ansible_host']:
ansible_host = host.variables_dict.get(host_var, '')
if ansible_host:
hostnames.add(ansible_host)
for hostname in hostnames:
try:
result = socket.getaddrinfo(hostname, None)
possible_ips = set(x[4][0] for x in result)
possible_ips.discard(hostname)
if possible_ips and possible_ips & remote_hosts:
matches.add(host)
except socket.gaierror:
pass
# Return all matches found.
for host_name in host_mappings:
try:
result = socket.getaddrinfo(host_name, None)
possible_ips = set(x[4][0] for x in result)
possible_ips.discard(host_name)
if possible_ips and possible_ips & remote_hosts:
matches.update(host_mappings[host_name])
except socket.gaierror:
pass
return matches
def get(self, request, *args, **kwargs):

View File

@ -545,6 +545,18 @@ class Host(CommonModelNameNotUnique):
self.ansible_facts[module] = facts
self.save()
def get_effective_host_name(self):
'''
Return the name of the host that will be used in actual ansible
command run.
'''
host_name = self.name
if 'ansible_ssh_host' in self.variables_dict:
host_name = self.variables_dict['ansible_ssh_host']
if 'ansible_host' in self.variables_dict:
host_name = self.variables_dict['ansible_host']
return host_name
class Group(CommonModelNameNotUnique):
'''

View File

@ -3,7 +3,7 @@ import yaml
from awx.api.serializers import JobLaunchSerializer
from awx.main.models.credential import Credential
from awx.main.models.inventory import Inventory
from awx.main.models.inventory import Inventory, Host
from awx.main.models.jobs import Job, JobTemplate
from awx.api.versioning import reverse
@ -431,3 +431,31 @@ def test_callback_ignore_unprompted_extra_var(mocker, survey_spec_factory, job_t
'limit': 'single-host'},)
mock_job.signal_start.assert_called_once()
@pytest.mark.django_db
@pytest.mark.job_runtime_vars
def test_callback_find_matching_hosts(mocker, get, job_template_prompts, admin_user):
job_template = job_template_prompts(False)
job_template.host_config_key = "foo"
job_template.save()
host_with_alias = Host(name='localhost', inventory=job_template.inventory)
host_with_alias.save()
with mocker.patch('awx.main.access.BaseAccess.check_license'):
r = get(reverse('api:job_template_callback', kwargs={'pk': job_template.pk}),
user=admin_user, expect=200)
assert tuple(r.data['matching_hosts']) == ('localhost',)
@pytest.mark.django_db
@pytest.mark.job_runtime_vars
def test_callback_extra_var_takes_priority_over_host_name(mocker, get, job_template_prompts, admin_user):
job_template = job_template_prompts(False)
job_template.host_config_key = "foo"
job_template.save()
host_with_alias = Host(name='localhost', variables={'ansible_host': 'foobar'}, inventory=job_template.inventory)
host_with_alias.save()
with mocker.patch('awx.main.access.BaseAccess.check_license'):
r = get(reverse('api:job_template_callback', kwargs={'pk': job_template.pk}),
user=admin_user, expect=200)
assert not r.data['matching_hosts']