diff --git a/awx/api/views/root.py b/awx/api/views/root.py index ac5592207f..9ab8ff0840 100644 --- a/awx/api/views/root.py +++ b/awx/api/views/root.py @@ -300,13 +300,7 @@ class ApiV2ConfigView(APIView): or Organization.accessible_objects(request.user, 'auditor_role').exists() or Organization.accessible_objects(request.user, 'project_admin_role').exists() ): - data.update( - dict( - project_base_dir=settings.PROJECTS_ROOT, project_local_paths=Project.get_local_path_choices(), custom_virtualenvs=get_custom_venv_choices() - ) - ) - elif JobTemplate.accessible_objects(request.user, 'admin_role').exists(): - data['custom_virtualenvs'] = get_custom_venv_choices() + data.update(dict(project_base_dir=settings.PROJECTS_ROOT, project_local_paths=Project.get_local_path_choices())) return Response(data) diff --git a/awx/main/analytics/collectors.py b/awx/main/analytics/collectors.py index 9755beeac9..9455c73bf0 100644 --- a/awx/main/analytics/collectors.py +++ b/awx/main/analytics/collectors.py @@ -15,7 +15,7 @@ from django.utils.translation import ugettext_lazy as _ from psycopg2.errors import UntranslatableCharacter from awx.conf.license import get_license -from awx.main.utils import get_awx_version, get_custom_venv_choices, camelcase_to_underscore, datetime_hook +from awx.main.utils import get_awx_version, camelcase_to_underscore, datetime_hook from awx.main import models from awx.main.analytics import register @@ -120,7 +120,7 @@ def config(since, **kwargs): } -@register('counts', '1.0', description=_('Counts of objects such as organizations, inventories, and projects')) +@register('counts', '1.1', description=_('Counts of objects such as organizations, inventories, and projects')) def counts(since, **kwargs): counts = {} for cls in ( @@ -138,9 +138,6 @@ def counts(since, **kwargs): ): counts[camelcase_to_underscore(cls.__name__)] = cls.objects.count() - venvs = get_custom_venv_choices() - counts['custom_virtualenvs'] = len([v for v in venvs if os.path.basename(v.rstrip('/')) != 'ansible']) - inv_counts = dict(models.Inventory.objects.order_by().values_list('kind').annotate(Count('kind'))) inv_counts['normal'] = inv_counts.get('', 0) inv_counts.pop('', None) diff --git a/awx/main/analytics/metrics.py b/awx/main/analytics/metrics.py index b9cd5153cc..a32a7fc959 100644 --- a/awx/main/analytics/metrics.py +++ b/awx/main/analytics/metrics.py @@ -39,7 +39,6 @@ def metrics(): ], registry=REGISTRY, ) - CUSTOM_VENVS = Gauge('awx_custom_virtualenvs_total', 'Number of virtualenvs', registry=REGISTRY) RUNNING_JOBS = Gauge('awx_running_jobs_total', 'Number of running jobs on the system', registry=REGISTRY) PENDING_JOBS = Gauge('awx_pending_jobs_total', 'Number of pending jobs on the system', registry=REGISTRY) STATUS = Gauge( @@ -159,7 +158,6 @@ def metrics(): HOST_COUNT.labels(type='active').set(current_counts['active_host_count']) SCHEDULE_COUNT.set(current_counts['schedule']) - CUSTOM_VENVS.set(current_counts['custom_virtualenvs']) USER_SESSIONS.labels(type='all').set(current_counts['active_sessions']) USER_SESSIONS.labels(type='user').set(current_counts['active_user_sessions']) diff --git a/awx/main/management/commands/custom_venvs.py b/awx/main/management/commands/custom_venvs.py new file mode 100644 index 0000000000..5a0489c7ee --- /dev/null +++ b/awx/main/management/commands/custom_venvs.py @@ -0,0 +1,28 @@ +# Copyright (c) 2021 Ansible, Inc. +# All Rights Reserved + +from awx.main.utils.common import get_custom_venv_choices, get_custom_venv_pip_freeze +from django.core.management.base import BaseCommand + + +class Command(BaseCommand): + """Returns either a list of custom venv paths or outputs the pip freeze from the path passed in the argument""" + + def add_arguments(self, parser): + parser.add_argument( + '--path', + dest='path', + type=str, + default='', + help='run without arguments to see a list of paths, run with one of those paths as an argument and see the pip freeze data', + ) + + def handle(self, *args, **options): + super(Command, self).__init__() + if options.get('path'): + pip_data = get_custom_venv_pip_freeze(options.get('path')) + print(pip_data) + else: + venvs = get_custom_venv_choices() + for venv in venvs: + print(venv) diff --git a/awx/main/tests/functional/analytics/test_counts.py b/awx/main/tests/functional/analytics/test_counts.py index 146afb604c..a55065b6bd 100644 --- a/awx/main/tests/functional/analytics/test_counts.py +++ b/awx/main/tests/functional/analytics/test_counts.py @@ -12,7 +12,6 @@ def test_empty(): "active_sessions": 0, "active_host_count": 0, "credential": 0, - "custom_virtualenvs": 0, # dev env ansible3 "host": 0, "inventory": 0, "inventories": {"normal": 0, "smart": 0}, diff --git a/awx/main/tests/functional/analytics/test_metrics.py b/awx/main/tests/functional/analytics/test_metrics.py index 2a04adcfce..3a8d1c4411 100644 --- a/awx/main/tests/functional/analytics/test_metrics.py +++ b/awx/main/tests/functional/analytics/test_metrics.py @@ -21,7 +21,6 @@ EXPECTED_VALUES = { 'awx_sessions_total': 0.0, 'awx_sessions_total': 0.0, 'awx_sessions_total': 0.0, - 'awx_custom_virtualenvs_total': 0.0, 'awx_running_jobs_total': 0.0, 'awx_instance_capacity': 100.0, 'awx_instance_consumed_capacity': 0.0, diff --git a/awx/main/utils/common.py b/awx/main/utils/common.py index 543f351d4e..644097b32a 100644 --- a/awx/main/utils/common.py +++ b/awx/main/utils/common.py @@ -6,6 +6,7 @@ import json import yaml import logging import os +import subprocess import re import stat import urllib.parse @@ -890,30 +891,34 @@ def get_current_apps(): return current_apps -def get_custom_venv_choices(custom_paths=None): +def get_custom_venv_choices(): from django.conf import settings - custom_paths = custom_paths or settings.CUSTOM_VENV_PATHS - all_venv_paths = [settings.BASE_VENV_PATH] + custom_paths + all_venv_paths = settings.CUSTOM_VENV_PATHS + [settings.BASE_VENV_PATH] custom_venv_choices = [] - for custom_venv_path in all_venv_paths: + for venv_path in all_venv_paths: try: - if os.path.exists(custom_venv_path): + if os.path.exists(venv_path): custom_venv_choices.extend( - [ - os.path.join(custom_venv_path, x, '') - for x in os.listdir(custom_venv_path) - if x != 'awx' - and os.path.isdir(os.path.join(custom_venv_path, x)) - and os.path.exists(os.path.join(custom_venv_path, x, 'bin', 'activate')) - ] + [os.path.join(venv_path, x) for x in os.listdir(venv_path) if os.path.exists(os.path.join(venv_path, x, 'bin', 'pip'))] ) except Exception: logger.exception("Encountered an error while discovering custom virtual environments.") return custom_venv_choices +def get_custom_venv_pip_freeze(venv_path): + venv_path = os.path.join(venv_path, 'bin', 'pip') + try: + if os.path.exists(venv_path): + freeze_data = subprocess.run([venv_path, "freeze"], capture_output=True) + pip_data = (freeze_data.stdout).decode('UTF-8') + return pip_data + except Exception: + logger.exception("Encountered an error while discovering Pip Freeze data for custom virtual environments.") + + def is_ansible_variable(key): return key.startswith('ansible_')