mirror of
https://github.com/ansible/awx.git
synced 2026-05-20 15:27:47 -02:30
[AAP-74343] Skip host query scanning when indirect counting flag is off
The indirect_instance_count callback plugin now checks AWX_COLLECT_HOST_QUERIES to decide whether to scan for host query files. When the feature flag is off, the plugin only collects collection metadata (name + version) and ansible_version, skipping the expensive embedded/external query file discovery. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1162,6 +1162,7 @@ class RunJob(SourceControlMixin, BaseTask):
|
|||||||
env['ANSIBLE_CALLBACKS_ENABLED'] += ',' + config_values['callbacks_enabled']
|
env['ANSIBLE_CALLBACKS_ENABLED'] += ',' + config_values['callbacks_enabled']
|
||||||
|
|
||||||
if flag_enabled("FEATURE_INDIRECT_NODE_COUNTING_ENABLED"):
|
if flag_enabled("FEATURE_INDIRECT_NODE_COUNTING_ENABLED"):
|
||||||
|
env['AWX_COLLECT_HOST_QUERIES'] = '1'
|
||||||
# Add vendor collections path for external query file discovery
|
# Add vendor collections path for external query file discovery
|
||||||
vendor_collections_path = os.path.join(CONTAINER_ROOT, 'vendor_collections')
|
vendor_collections_path = os.path.join(CONTAINER_ROOT, 'vendor_collections')
|
||||||
env['ANSIBLE_COLLECTIONS_PATH'] = f"{vendor_collections_path}:{env['ANSIBLE_COLLECTIONS_PATH']}"
|
env['ANSIBLE_COLLECTIONS_PATH'] = f"{vendor_collections_path}:{env['ANSIBLE_COLLECTIONS_PATH']}"
|
||||||
|
|||||||
@@ -965,6 +965,33 @@ class TestCallbacksEnabled(TestJobExecution):
|
|||||||
|
|
||||||
assert env['ANSIBLE_CALLBACKS_ENABLED'] == 'indirect_instance_count,my_callback'
|
assert env['ANSIBLE_CALLBACKS_ENABLED'] == 'indirect_instance_count,my_callback'
|
||||||
|
|
||||||
|
def test_collect_host_queries_set_when_flag_on(self, patch_Job, private_data_dir, execution_environment, mock_me):
|
||||||
|
job = Job(project=Project(), inventory=Inventory())
|
||||||
|
job.execution_environment = execution_environment
|
||||||
|
|
||||||
|
task = jobs.RunJob()
|
||||||
|
task.instance = job
|
||||||
|
task._write_extra_vars_file = mock.Mock()
|
||||||
|
|
||||||
|
with mock.patch.object(task, 'build_credentials_list', return_value=[], autospec=True):
|
||||||
|
with mock.patch('awx.main.tasks.jobs.flag_enabled', return_value=True):
|
||||||
|
env = task.build_env(job, private_data_dir)
|
||||||
|
|
||||||
|
assert env['AWX_COLLECT_HOST_QUERIES'] == '1'
|
||||||
|
|
||||||
|
def test_collect_host_queries_not_set_when_flag_off(self, patch_Job, private_data_dir, execution_environment, mock_me):
|
||||||
|
job = Job(project=Project(), inventory=Inventory())
|
||||||
|
job.execution_environment = execution_environment
|
||||||
|
|
||||||
|
task = jobs.RunJob()
|
||||||
|
task.instance = job
|
||||||
|
task._write_extra_vars_file = mock.Mock()
|
||||||
|
|
||||||
|
with mock.patch.object(task, 'build_credentials_list', return_value=[], autospec=True):
|
||||||
|
env = task.build_env(job, private_data_dir)
|
||||||
|
|
||||||
|
assert 'AWX_COLLECT_HOST_QUERIES' not in env
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("patch_Organization")
|
@pytest.mark.usefixtures("patch_Organization")
|
||||||
class TestProjectUpdateGalaxyCredentials(TestJobExecution):
|
class TestProjectUpdateGalaxyCredentials(TestJobExecution):
|
||||||
|
|||||||
@@ -168,29 +168,28 @@ class CallbackModule(CallbackBase):
|
|||||||
if not artifact_dir:
|
if not artifact_dir:
|
||||||
raise RuntimeError('Only suitable in AWX, did not find private_data_dir')
|
raise RuntimeError('Only suitable in AWX, did not find private_data_dir')
|
||||||
|
|
||||||
|
collect_host_queries = os.getenv('AWX_COLLECT_HOST_QUERIES') == '1'
|
||||||
|
|
||||||
collections_print = {}
|
collections_print = {}
|
||||||
# Loop over collections, from ansible-core these are Candidate objects
|
|
||||||
for candidate in list_collections():
|
for candidate in list_collections():
|
||||||
collection_print = {
|
collection_print = {
|
||||||
'version': candidate.ver,
|
'version': candidate.ver,
|
||||||
}
|
}
|
||||||
|
|
||||||
# 1. Check for embedded query file (takes precedence)
|
if collect_host_queries:
|
||||||
embedded_query_file = files(f'ansible_collections.{candidate.namespace}.{candidate.name}') / 'extensions' / 'audit' / 'event_query.yml'
|
embedded_query_file = files(f'ansible_collections.{candidate.namespace}.{candidate.name}') / 'extensions' / 'audit' / 'event_query.yml'
|
||||||
if embedded_query_file.exists():
|
if embedded_query_file.exists():
|
||||||
with embedded_query_file.open('r') as f:
|
with embedded_query_file.open('r') as f:
|
||||||
collection_print['host_query'] = f.read()
|
collection_print['host_query'] = f.read()
|
||||||
self._display.vv(f"Using embedded query for {candidate.fqcn} v{candidate.ver}")
|
self._display.vv(f"Using embedded query for {candidate.fqcn} v{candidate.ver}")
|
||||||
else:
|
else:
|
||||||
# 2. Check for external query file with version fallback
|
query_content, fallback_used, version_used = find_external_query_with_fallback(candidate.namespace, candidate.name, candidate.ver)
|
||||||
query_content, fallback_used, version_used = find_external_query_with_fallback(candidate.namespace, candidate.name, candidate.ver)
|
if query_content:
|
||||||
if query_content:
|
collection_print['host_query'] = query_content
|
||||||
collection_print['host_query'] = query_content
|
if fallback_used:
|
||||||
if fallback_used:
|
self._display.v(f"Using external query {version_used} for {candidate.fqcn} v{candidate.ver}.")
|
||||||
# AC5.6: Log when fallback is used
|
else:
|
||||||
self._display.v(f"Using external query {version_used} for {candidate.fqcn} v{candidate.ver}.")
|
self._display.v(f"Using external query for {candidate.fqcn} v{candidate.ver}")
|
||||||
else:
|
|
||||||
self._display.v(f"Using external query for {candidate.fqcn} v{candidate.ver}")
|
|
||||||
|
|
||||||
collections_print[candidate.fqcn] = collection_print
|
collections_print[candidate.fqcn] = collection_print
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user