diff --git a/awx/main/models/credential.py b/awx/main/models/credential.py index 44f310716da9..5e915b54e56e 100644 --- a/awx/main/models/credential.py +++ b/awx/main/models/credential.py @@ -53,7 +53,6 @@ ) from awx.main.models import Team, Organization from awx.main.utils import encrypt_field -from awx_plugins.credentials import injectors as builtin_injectors # DAB from ansible_base.resource_registry.tasks.sync import get_resource_server_client @@ -438,6 +437,7 @@ class Meta: default=dict, help_text=_('Enter injectors using either JSON or YAML syntax. Refer to the documentation for example syntax.'), ) + custom_injectors = None @classmethod def from_db(cls, db, field_names, values): @@ -446,6 +446,7 @@ def from_db(cls, db, field_names, values): native = ManagedCredentialType.registry[instance.namespace] instance.inputs = native.inputs instance.injectors = native.injectors + instance.custom_injectors = native.custom_injectors return instance def get_absolute_url(self, request=None): @@ -547,6 +548,7 @@ def setup_tower_managed_defaults(cls, apps: Apps = None, app_config: AppConfig = @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) def inject_credential(self, credential, env, safe_env, args, private_data_dir): @@ -575,9 +577,9 @@ def inject_credential(self, credential, env, safe_env, args, private_data_dir): files) """ if not self.injectors: - if self.managed and credential.credential_type.namespace in dir(builtin_injectors): + if self.managed and credential.credential_type.custom_injectors: injected_env = {} - getattr(builtin_injectors, credential.credential_type.namespace)(credential, injected_env, private_data_dir) + credential.credential_type.custom_injectors(credential, injected_env, private_data_dir) env.update(injected_env) safe_env.update(build_safe_env(injected_env)) return @@ -686,6 +688,7 @@ def __init__(self, namespace, **kwargs): for k in ('inputs', 'injectors'): if k not in kwargs: kwargs[k] = {} + kwargs.setdefault('custom_injectors', None) super(ManagedCredentialType, self).__init__(namespace=namespace, **kwargs) if namespace in ManagedCredentialType.registry: raise ValueError( @@ -706,7 +709,9 @@ def get_creation_params(self): ) def create(self): - return CredentialType(**self.get_creation_params()) + res = CredentialType(**self.get_creation_params()) + res.custom_injectors = self.custom_injectors + return res class CredentialInputSource(PrimordialModel): diff --git a/awx/main/tests/functional/test_inventory_source_injectors.py b/awx/main/tests/functional/test_inventory_source_injectors.py index 83d9360ff501..c7ab3d440c82 100644 --- a/awx/main/tests/functional/test_inventory_source_injectors.py +++ b/awx/main/tests/functional/test_inventory_source_injectors.py @@ -192,9 +192,10 @@ def create_reference_data(source_dir, env, content): json.dump(env, f, indent=4, sort_keys=True) +@mock.patch('awx_plugins.interfaces._temporary_private_licensing_api.detect_server_product_name', return_value='NOT-AWX') @pytest.mark.django_db @pytest.mark.parametrize('this_kind', discover_available_cloud_provider_plugin_names()) -def test_inventory_update_injected_content(this_kind, inventory, fake_credential_factory, mock_me): +def test_inventory_update_injected_content(product_name, this_kind, inventory, fake_credential_factory, mock_me): if this_kind.endswith('_supported'): this_kind = this_kind[:-10]