From f05173cb65cbbd1de90e0b95740cffe22859f222 Mon Sep 17 00:00:00 2001 From: Jake Jackson Date: Wed, 15 Jan 2025 16:10:28 -0500 Subject: Add new credential entry point discovery (#15685) * - add new entry points - add logic to check what version of the project is running * remove former discovery method * update custom_injectors and remove unused import * fix how we load external creds * remove stale code to match devel * fix cloudforms test and move credential loading * add load credentials method to get tests passing * Conditionalize integration tests if the cred is present * remove inventory source test * inventory source is covered in the workflow job template target --- awx/main/apps.py | 3 + awx/main/models/credential.py | 83 +++++++----- awx/main/tests/conftest.py | 9 ++ .../migrations/test_inventory_source_migration.py | 16 ++- awx/main/tests/live/tests/conftest.py | 1 + awx_collection/test/awx/conftest.py | 1 + .../integration/targets/credential/tasks/main.yml | 53 ++++++++ .../targets/credential_input_source/tasks/main.yml | 16 ++- .../integration/targets/inventory/tasks/main.yml | 23 ---- .../targets/inventory_source/tasks/main.yml | 143 --------------------- .../targets/workflow_job_template/tasks/main.yml | 41 ++++-- requirements/requirements_git.txt | 2 +- 12 files changed, 172 insertions(+), 219 deletions(-) delete mode 100644 awx_collection/tests/integration/targets/inventory_source/tasks/main.yml diff --git a/awx/main/apps.py b/awx/main/apps.py index 3d98963747..c1c90f83c7 100644 --- a/awx/main/apps.py +++ b/awx/main/apps.py @@ -60,6 +60,9 @@ class MainConfig(AppConfig): @bypass_in_test def load_credential_types_feature(self): + from awx.main.models.credential import load_credentials + + load_credentials() return self._load_credential_types_feature() def load_inventory_plugins(self): diff --git a/awx/main/models/credential.py b/awx/main/models/credential.py index 09cc4bde7c..b9bacaae4c 100644 --- a/awx/main/models/credential.py +++ b/awx/main/models/credential.py @@ -2,6 +2,7 @@ # All Rights Reserved. from contextlib import nullcontext import functools + import inspect import logging from importlib.metadata import entry_points @@ -47,6 +48,8 @@ from awx.main.models.rbac import ( ) from awx.main.models import Team, Organization from awx.main.utils import encrypt_field +from awx_plugins.interfaces._temporary_private_licensing_api import detect_server_product_name + # DAB from ansible_base.resource_registry.tasks.sync import get_resource_server_client @@ -56,7 +59,6 @@ from ansible_base.resource_registry.utils.settings import resource_server_define __all__ = ['Credential', 'CredentialType', 'CredentialInputSource', 'build_safe_env'] logger = logging.getLogger('awx.main.models.credential') -credential_plugins = {entry_point.name: entry_point.load() for entry_point in entry_points(group='awx_plugins.credentials')} HIDDEN_PASSWORD = '**********' @@ -462,8 +464,7 @@ class CredentialType(CommonModelNameNotUnique): def plugin(self): if self.kind != 'external': raise AttributeError('plugin') - [plugin] = [plugin for ns, plugin in credential_plugins.items() if ns == self.namespace] - return plugin + return ManagedCredentialType.registry.get(self.namespace, None) def default_for_field(self, field_id): for field in self.inputs.get('fields', []): @@ -474,7 +475,7 @@ class CredentialType(CommonModelNameNotUnique): @classproperty def defaults(cls): - return dict((k, functools.partial(v.create)) for k, v in ManagedCredentialType.registry.items()) + return dict((k, functools.partial(CredentialTypeHelper.create, v)) for k, v in ManagedCredentialType.registry.items()) @classmethod def _get_credential_type_class(cls, apps: Apps = None, app_config: AppConfig = None): @@ -509,7 +510,7 @@ class CredentialType(CommonModelNameNotUnique): existing.save() continue logger.debug(_("adding %s credential type" % default.name)) - params = default.get_creation_params() + params = CredentialTypeHelper.get_creation_params(default) if 'managed' not in [f.name for f in ct_class._meta.get_fields()]: params['managed_by_tower'] = params.pop('managed') params['created'] = params['modified'] = now() # CreatedModifiedModel service @@ -543,7 +544,7 @@ class CredentialType(CommonModelNameNotUnique): @classmethod def load_plugin(cls, ns, plugin): # TODO: User "side-loaded" credential custom_injectors isn't supported - ManagedCredentialType(namespace=ns, name=plugin.name, kind='external', inputs=plugin.inputs) + ManagedCredentialType.registry[ns] = ManagedCredentialType(namespace=ns, name=plugin.name, kind='external', inputs=plugin.inputs, injectors={}) def inject_credential(self, credential, env, safe_env, args, private_data_dir): from awx_plugins.interfaces._temporary_private_inject_api import inject_credential @@ -551,38 +552,29 @@ class CredentialType(CommonModelNameNotUnique): inject_credential(self, credential, env, safe_env, args, private_data_dir) -class ManagedCredentialType(SimpleNamespace): - registry = {} - - def __init__(self, namespace, **kwargs): - for k in ('inputs', 'injectors'): - if k not in kwargs: - kwargs[k] = {} - super(ManagedCredentialType, self).__init__(namespace=namespace, **kwargs) - if namespace in ManagedCredentialType.registry: - raise ValueError( - 'a ManagedCredentialType with namespace={} is already defined in {}'.format( - namespace, inspect.getsourcefile(ManagedCredentialType.registry[namespace].__class__) - ) - ) - ManagedCredentialType.registry[namespace] = self - - def get_creation_params(self): +class CredentialTypeHelper: + @classmethod + def get_creation_params(cls, cred_type): return dict( - namespace=self.namespace, - kind=self.kind, - name=self.name, + namespace=cred_type.namespace, + kind=cred_type.kind, + name=cred_type.name, managed=True, - inputs=self.inputs, - injectors=self.injectors, + inputs=cred_type.inputs, + injectors=cred_type.injectors, ) - def create(self): - res = CredentialType(**self.get_creation_params()) - res.custom_injectors = getattr(self, 'custom_injectors', None) + @classmethod + def create(cls, cred_type): + res = CredentialType(**CredentialTypeHelper.get_creation_params(cred_type)) + res.custom_injectors = getattr(cred_type, "custom_injectors", None) return res +class ManagedCredentialType(SimpleNamespace): + registry = {} + + class CredentialInputSource(PrimordialModel): class Meta: app_label = 'main' @@ -647,7 +639,30 @@ class CredentialInputSource(PrimordialModel): return reverse(view_name, kwargs={'pk': self.pk}, request=request) -from awx_plugins.credentials.plugins import * # noqa +def load_credentials(): + + awx_entry_points = {ep.name: ep for ep in entry_points(group='awx_plugins.managed_credentials')} + supported_entry_points = {ep.name: ep for ep in entry_points(group='awx_plugins.managed_credentials.supported')} + plugin_entry_points = awx_entry_points if detect_server_product_name() == 'AWX' else {**awx_entry_points, **supported_entry_points} + + for ns, ep in plugin_entry_points.items(): + cred_plugin = ep.load() + if not hasattr(cred_plugin, 'inputs'): + setattr(cred_plugin, 'inputs', {}) + if not hasattr(cred_plugin, 'injectors'): + setattr(cred_plugin, 'injectors', {}) + if ns in ManagedCredentialType.registry: + raise ValueError( + 'a ManagedCredentialType with namespace={} is already defined in {}'.format( + ns, inspect.getsourcefile(ManagedCredentialType.registry[ns].__class__) + ) + ) + ManagedCredentialType.registry[ns] = cred_plugin + + credential_plugins = {ep.name: ep for ep in entry_points(group='awx_plugins.credentials')} + if detect_server_product_name() == 'AWX': + credential_plugins = {} -for ns, plugin in credential_plugins.items(): - CredentialType.load_plugin(ns, plugin) + for ns, ep in credential_plugins.items(): + plugin = ep.load() + CredentialType.load_plugin(ns, plugin) diff --git a/awx/main/tests/conftest.py b/awx/main/tests/conftest.py index e1a1c05e00..fbfb6489f0 100644 --- a/awx/main/tests/conftest.py +++ b/awx/main/tests/conftest.py @@ -229,3 +229,12 @@ def me_inst(): me_mock = mock.MagicMock(return_value=inst) with mock.patch.object(Instance.objects, 'me', me_mock): yield inst + + +@pytest.fixture(scope="session", autouse=True) +def load_all_credentials(): + with mock.patch('awx.main.models.credential.detect_server_product_name', return_value='NOT_AWX'): + from awx.main.models.credential import load_credentials + + load_credentials() + yield diff --git a/awx/main/tests/functional/migrations/test_inventory_source_migration.py b/awx/main/tests/functional/migrations/test_inventory_source_migration.py index fe0b537426..6d17e22936 100644 --- a/awx/main/tests/functional/migrations/test_inventory_source_migration.py +++ b/awx/main/tests/functional/migrations/test_inventory_source_migration.py @@ -37,16 +37,24 @@ def cleanup_cloudforms(): assert 'cloudforms' not in CredentialType.defaults -@pytest.mark.django_db -def test_cloudforms_inventory_removal(request, inventory): - request.addfinalizer(cleanup_cloudforms) - ManagedCredentialType( +@pytest.fixture +def cloudforms_mct(): + ManagedCredentialType.registry['cloudforms'] = ManagedCredentialType( name='Red Hat CloudForms', namespace='cloudforms', kind='cloud', managed=True, inputs={}, + injectors={}, ) + yield + ManagedCredentialType.registry.pop('cloudforms', None) + + +@pytest.mark.django_db +def test_cloudforms_inventory_removal(request, inventory, cloudforms_mct): + request.addfinalizer(cleanup_cloudforms) + CredentialType.defaults['cloudforms']().save() cloudforms = CredentialType.objects.get(namespace='cloudforms') Credential.objects.create( diff --git a/awx/main/tests/live/tests/conftest.py b/awx/main/tests/live/tests/conftest.py index 0fae039189..f7c197199f 100644 --- a/awx/main/tests/live/tests/conftest.py +++ b/awx/main/tests/live/tests/conftest.py @@ -5,6 +5,7 @@ import pytest # These tests are invoked from the awx/main/tests/live/ subfolder # so any fixtures from higher-up conftest files must be explicitly included from awx.main.tests.functional.conftest import * # noqa +from awx.main.tests.conftest import load_all_credentials # noqa: F401; pylint: disable=unused-import from awx.main.models import Organization diff --git a/awx_collection/test/awx/conftest.py b/awx_collection/test/awx/conftest.py index 42500342ac..6de5ed9c25 100644 --- a/awx_collection/test/awx/conftest.py +++ b/awx_collection/test/awx/conftest.py @@ -18,6 +18,7 @@ import pytest from ansible.module_utils.six import raise_from from ansible_base.rbac.models import RoleDefinition, DABPermission +from awx.main.tests.conftest import load_all_credentials # noqa: F401; pylint: disable=unused-import from awx.main.tests.functional.conftest import _request from awx.main.tests.functional.conftest import credentialtype_scm, credentialtype_ssh # noqa: F401; pylint: disable=unused-import from awx.main.models import ( diff --git a/awx_collection/tests/integration/targets/credential/tasks/main.yml b/awx_collection/tests/integration/targets/credential/tasks/main.yml index 043deea185..76be783454 100644 --- a/awx_collection/tests/integration/targets/credential/tasks/main.yml +++ b/awx_collection/tests/integration/targets/credential/tasks/main.yml @@ -25,6 +25,21 @@ insights_cred_name2: "AWX-Collection-tests-credential-insights-cred2-{{ test_id }}" tower_cred_name1: "AWX-Collection-tests-credential-tower-cred1-{{ test_id }}" +- name: Get current Credential Types available + ansible.builtin.set_fact: + credentials: "{{ lookup('awx.awx.controller_api', 'credential_types') }}" + +- name: Register Credentials found + set_fact: + aws_found: "{{ 'Amazon Web Services' in credentials | map(attribute='name') | list }}" + vmware_found: "{{ 'VMware vCenter' in credentials | map(attribute='name') | list }}" + azure_found: "{{ 'Microsoft Azure Resource Manager' in credentials | map(attribute='name') | list }}" + gce_found: "{{ 'Google Compute Engine' in credentials | map(attribute='name') | list }}" + insights_found: "{{ 'Red Hat Insights' in credentials | map(attribute='name') | list }}" + satellite_found: "{{ 'Red Hat Satellite 6' in credentials | map(attribute='name') | list }}" + openstack_found: "{{ 'OpenStack' in credentials | map(attribute='name') | list }}" + rhv_found: "{{ 'Red Hat Virtualization' in credentials | map(attribute='name') | list }}" + - name: create a tempdir for an SSH key local_action: shell mktemp -d register: tempdir @@ -464,10 +479,12 @@ password: secret security_token: aws-token register: result + when: aws_found - assert: that: - "result is changed" + when: aws_found - name: Delete an AWS credential credential: @@ -476,10 +493,12 @@ state: absent credential_type: Amazon Web Services register: result + when: aws_found - assert: that: - "result is changed" + when: aws_found - name: Create a valid VMWare credential credential: @@ -492,10 +511,12 @@ username: joe password: secret register: result + when: vmware_found - assert: that: - "result is changed" + when: vmware_found - name: Delete an VMWare credential credential: @@ -504,10 +525,12 @@ state: absent credential_type: VMware vCenter register: result + when: vmware_found - assert: that: - "result is changed" + when: vmware_found - name: Create a valid Satellite6 credential credential: @@ -520,10 +543,12 @@ username: joe password: secret register: result + when: satellite_found - assert: that: - "result is changed" + when: satellite_found - name: Delete a Satellite6 credential credential: @@ -532,10 +557,12 @@ state: absent credential_type: Red Hat Satellite 6 register: result + when: satellite_found - assert: that: - "result is changed" + when: satellite_found - name: Create a valid GCE credential credential: @@ -548,10 +575,12 @@ project: ABC123 ssh_key_data: "{{ ssh_key_data }}" register: result + when: gce_found - assert: that: - "result is changed" + when: gce_found - name: Delete a GCE credential credential: @@ -560,10 +589,12 @@ state: absent credential_type: Google Compute Engine register: result + when: gce_found - assert: that: - "result is changed" + when: gce_found - name: Create a valid AzureRM credential credential: @@ -576,10 +607,12 @@ password: secret subscription: some-subscription register: result + when: azure_found - assert: that: - "result is changed" + when: azure_found - name: Create a valid AzureRM credential with a tenant credential: @@ -593,10 +626,12 @@ tenant: some-tenant subscription: some-subscription register: result + when: azure_found - assert: that: - "result is changed" + when: azure_found - name: Delete an AzureRM credential credential: @@ -605,10 +640,12 @@ state: absent credential_type: Microsoft Azure Resource Manager register: result + when: azure_found - assert: that: - "result is changed" + when: azure_found - name: Create a valid OpenStack credential credential: @@ -623,10 +660,12 @@ project: tenant123 domain: some-domain register: result + when: openstack_found - assert: that: - "result is changed" + when: openstack_found - name: Delete a OpenStack credential credential: @@ -635,10 +674,12 @@ state: absent credential_type: OpenStack register: result + when: openstack_found - assert: that: - "result is changed" + when: openstack_found - name: Create a valid RHV credential credential: @@ -651,10 +692,12 @@ username: joe password: secret register: result + when: rhv_found - assert: that: - "result is changed" + when: rhv_found - name: Delete an RHV credential credential: @@ -663,10 +706,12 @@ state: absent credential_type: Red Hat Virtualization register: result + when: rhv_found - assert: that: - "result is changed" + when: rhv_found - name: Create a valid Insights credential credential: @@ -678,10 +723,12 @@ username: joe password: secret register: result + when: insights_found - assert: that: - "result is changed" + when: insights_found - name: Delete an Insights credential credential: @@ -690,10 +737,12 @@ state: absent credential_type: Insights register: result + when: insights_found - assert: that: - "result is changed" + when: insights_found - name: Create a valid Insights token credential credential: @@ -705,10 +754,12 @@ client_id: joe client_secret: secret register: result + when: insights_found - assert: that: - "result is changed" + when: insights_found - name: Delete an Insights token credential credential: @@ -717,10 +768,12 @@ state: absent credential_type: Insights register: result + when: insights_found - assert: that: - "result is changed" + when: insights_found - name: Create a valid Tower-to-Tower credential credential: diff --git a/awx_collection/tests/integration/targets/credential_input_source/tasks/main.yml b/awx_collection/tests/integration/targets/credential_input_source/tasks/main.yml index 1d56d5e4b1..d5568fdd8d 100644 --- a/awx_collection/tests/integration/targets/credential_input_source/tasks/main.yml +++ b/awx_collection/tests/integration/targets/credential_input_source/tasks/main.yml @@ -9,7 +9,17 @@ src_cred_name: "AWX-Collection-tests-credential_input_source-src_cred-{{ test_id }}" target_cred_name: "AWX-Collection-tests-credential_input_source-target_cred-{{ test_id }}" -- block: +- name: detect credential types + ansible.builtin.set_fact: + credentials: "{{ lookup('awx.awx.controller_api', 'credential_types') }}" + +- name: Register Credentials found + set_fact: + cyberark_found: "{{ 'CyberArk Central Credential Provider Lookup' in credentials | map(attribute='name') | list }}" + +- name: Test credential lookup workflow + when: cyberark_found + block: - name: Add credential Lookup credential: description: Credential for Testing Source @@ -121,7 +131,9 @@ that: - "result is changed" - always: +- name: Clean up if previous block ran + when: cyberark_found + block: - name: Remove a credential source credential_input_source: input_field_name: password diff --git a/awx_collection/tests/integration/targets/inventory/tasks/main.yml b/awx_collection/tests/integration/targets/inventory/tasks/main.yml index dbaf7dbcec..b3a72fd033 100644 --- a/awx_collection/tests/integration/targets/inventory/tasks/main.yml +++ b/awx_collection/tests/integration/targets/inventory/tasks/main.yml @@ -8,7 +8,6 @@ set_fact: inv_name1: "AWX-Collection-tests-inventory-inv1-{{ test_id }}" inv_name2: "AWX-Collection-tests-inventory-inv2-{{ test_id }}" - cred_name1: "AWX-Collection-tests-inventory-cred1-{{ test_id }}" group_name1: "AWX-Collection-tests-instance_group-group1-{{ test_id }}" - block: @@ -23,21 +22,6 @@ that: - "result is changed" - - name: Create an Insights Credential - credential: - name: "{{ cred_name1 }}" - organization: Default - credential_type: Insights - inputs: - username: joe - password: secret - state: present - register: result - - - assert: - that: - - "result is changed" - - name: Create an Inventory inventory: name: "{{ inv_name1 }}" @@ -227,10 +211,3 @@ instance_group: name: "{{ group_name1 }}" state: absent - - - name: Delete Insights Credential - credential: - name: "{{ cred_name1 }}" - organization: "Default" - credential_type: Insights - state: absent diff --git a/awx_collection/tests/integration/targets/inventory_source/tasks/main.yml b/awx_collection/tests/integration/targets/inventory_source/tasks/main.yml deleted file mode 100644 index a0442eeaf2..0000000000 --- a/awx_collection/tests/integration/targets/inventory_source/tasks/main.yml +++ /dev/null @@ -1,143 +0,0 @@ ---- -- name: Generate a test ID - set_fact: - test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" - when: test_id is not defined - -- name: Generate names - set_fact: - openstack_cred: "AWX-Collection-tests-inventory_source-cred-openstack-{{ test_id }}" - openstack_inv: "AWX-Collection-tests-inventory_source-inv-openstack-{{ test_id }}" - openstack_inv_source: "AWX-Collection-tests-inventory_source-inv-source-openstack-{{ test_id }}" - -- name: Add a credential - credential: - description: Credentials for Openstack Test project - name: "{{ openstack_cred }}" - credential_type: OpenStack - organization: Default - inputs: - project: Test - username: admin - host: https://example.org:5000 - password: passw0rd - domain: test - register: credential_result - -- name: Add an inventory - inventory: - description: Test inventory - organization: Default - name: "{{ openstack_inv }}" - -- name: Create an source inventory - inventory_source: - name: "{{ openstack_inv_source }}" - description: Source for Test inventory - inventory: "{{ openstack_inv }}" - credential: "{{ credential_result.id }}" - overwrite: true - update_on_launch: true - source_vars: - private: false - source: openstack - register: result - -- assert: - that: - - "result is changed" - -- name: Create an source inventory with exists - inventory_source: - name: "{{ openstack_inv_source }}" - description: Source for Test inventory - inventory: "{{ openstack_inv }}" - credential: "{{ credential_result.id }}" - overwrite: true - update_on_launch: true - source_vars: - private: false - source: openstack - state: exists - register: result - -- assert: - that: - - "result is not changed" - -- name: Delete an source inventory - inventory_source: - name: "{{ openstack_inv_source }}" - description: Source for Test inventory - inventory: "{{ openstack_inv }}" - credential: "{{ credential_result.id }}" - overwrite: true - update_on_launch: true - source_vars: - private: false - source: openstack - state: absent - register: result - -- assert: - that: - - "result is changed" - -- name: Create an source inventory with exists - inventory_source: - name: "{{ openstack_inv_source }}" - description: Source for Test inventory - inventory: "{{ openstack_inv }}" - credential: "{{ credential_result.id }}" - overwrite: true - update_on_launch: true - source_vars: - private: false - source: openstack - state: exists - register: result - -- assert: - that: - - "result is changed" - -- name: Delete the inventory source with an invalid cred and source_project specified - inventory_source: - name: "{{ result.id }}" - inventory: "{{ openstack_inv }}" - credential: "Does Not Exit" - source_project: "Does Not Exist" - state: absent - -- assert: - that: - - "result is changed" - -- name: Delete the credential - credential: - description: Credentials for Openstack Test project - name: "{{ openstack_cred }}" - credential_type: OpenStack - organization: Default - inputs: - project: Test - username: admin - host: https://example.org:5000 - password: passw0rd - domain: test - state: absent - -- assert: - that: - - "result is changed" - -- name: Delete the inventory - inventory: - description: Test inventory - organization: Default - name: "{{ openstack_inv }}" - state: absent - -- assert: - that: - - "result is changed" diff --git a/awx_collection/tests/integration/targets/workflow_job_template/tasks/main.yml b/awx_collection/tests/integration/targets/workflow_job_template/tasks/main.yml index f051e47ad9..e3f25c415d 100644 --- a/awx_collection/tests/integration/targets/workflow_job_template/tasks/main.yml +++ b/awx_collection/tests/integration/targets/workflow_job_template/tasks/main.yml @@ -28,6 +28,14 @@ ig2: "AWX-Collection-tests-workflow_job_template-ig2-{{ test_id }}" host1: "AWX-Collection-tests-workflow_job_template-h1-{{ test_id }}" +- name: detect credential types + ansible.builtin.set_fact: + credentials: "{{ lookup('awx.awx.controller_api', 'credential_types') }}" + +- name: Register Credentials found + set_fact: + github_found: "{{ 'Github Personal Access Token' in credentials | map(attribute='name') | list }}" + - block: - name: "Create a new organization" organization: @@ -36,22 +44,30 @@ - Ansible Galaxy register: result - - name: Create Credentials + - name: Create SCM Credential credential: - name: "{{ item.name }}" + name: "{{ scm_cred_name }}" organization: Default - credential_type: "{{ item.type }}" + credential_type: Source Control register: result - loop: - - name: "{{ scm_cred_name }}" - type: Source Control - - name: "{{ github_webhook_credential_name }}" - type: GitHub Personal Access Token - assert: that: - "result is changed" + - name: Create Github PAT Credential + credential: + name: "{{ github_webhook_credential_name }}" + organization: Default + credential_type: Github Personal Access Token + register: result + when: github_found + + - assert: + that: + - "result is changed" + when: github_found + - name: Add email notification notification_template: name: "{{ email_not }}" @@ -867,8 +883,8 @@ name: "{{ webhook_wfjt_name }}" organization: Default inventory: Demo Inventory - webhook_service: gitlab - webhook_credential: "{{ github_webhook_credential_name }}" + webhook_service: "{{ 'gitlab' if github_found else omit }}" + webhook_credential: "{{ github_webhook_credential_name if github_found else omit }}" ignore_errors: true register: result @@ -876,14 +892,15 @@ that: - result is failed - "'Must match the selected webhook service' in result['msg']" + when: github_found and gitlab_found - name: Create a workflow job template with a GitHub webhook and a GitHub credential workflow_job_template: name: "{{ webhook_wfjt_name }}" organization: Default inventory: Demo Inventory - webhook_service: github - webhook_credential: "{{ github_webhook_credential_name }}" + webhook_service: "{{ 'github' if github_found else omit }}" + webhook_credential: "{{ github_webhook_credential_name if github_found else omit }}" register: result - assert: diff --git a/requirements/requirements_git.txt b/requirements/requirements_git.txt index 9818bb7f52..07e0b8878c 100644 --- a/requirements/requirements_git.txt +++ b/requirements/requirements_git.txt @@ -2,5 +2,5 @@ git+https://github.com/ansible/system-certifi.git@devel#egg=certifi # Remove pbr from requirements.in when moving ansible-runner to requirements.in git+https://github.com/ansible/ansible-runner.git@devel#egg=ansible-runner django-ansible-base @ git+https://github.com/ansible/django-ansible-base@devel#egg=django-ansible-base[rest-filters,jwt_consumer,resource-registry,rbac] -awx-plugins-core @ git+https://git@github.com/ansible/awx-plugins.git@devel#egg=awx-plugins-core +awx-plugins-core @ git+https://github.com/ansible/awx-plugins.git@devel#egg=awx-plugins-core awx_plugins.interfaces @ git+https://github.com/ansible/awx_plugins.interfaces.git -- cgit v1.2.3