Skip to content

Commit

Permalink
📦 Declare awx entry points for moved plugins
Browse files Browse the repository at this point in the history
This patch includes tests for loading them.
  • Loading branch information
chrismeyersfsu authored and webknjaz committed Aug 29, 2024
1 parent c212f6e commit 60dc36c
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 21 deletions.
29 changes: 23 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,29 @@ name = "Ansible maintainers and contributors"
# PLUGIN ACTIVATION GUIDANCE (UX):
# `pip install awx_plugins.credentials.x` would auto-activate any plugins the packaged project ships
[project.entry-points."awx_plugins.credentials"] # new entry points group name
x = "awx_plugins.credentials.x.api:XPlugin"

# awx calls `importlib.metadata.entry_points(group='awx.credential_plugins')` to discover and later enable any plugins present in the same env
[project.entry-points."awx.credential_plugins"] # pre-existing entry points group name
x = "awx_plugins.credentials.x.api:XPlugin"
# conjur = awx.main.credential_plugins.conjur:conjur_plugin
conjur = "awx_plugins.credentials.conjur:conjur_plugin"
hashivault_kv = "awx_plugins.credentials.hashivault:hashivault_kv_plugin"
hashivault_ssh = "awx_plugins.credentials.hashivault:hashivault_ssh_plugin"
azure_kv = "awx_plugins.credentials.azure_kv:azure_keyvault_plugin"
aim = "awx_plugins.credentials.aim:aim_plugin"
centrify_vault_kv = "awx_plugins.credentials.centrify_vault:centrify_plugin"
thycotic_dsv = "awx_plugins.credentials.dsv:dsv_plugin"
thycotic_tss = "awx_plugins.credentials.tss:tss_plugin"
aws_secretsmanager_credential = "awx_plugins.credentials.aws_secretsmanager:aws_secretmanager_plugin"

[project.entry-points."awx_plugins.inventory"] # new entry points group name
azure-rm = "awx_plugins.inventory.plugins:azure_rm"
ec2 = "awx_plugins.inventory.plugins:ec2"
gce = "awx_plugins.inventory.plugins:gce"
vmware = "awx_plugins.inventory.plugins:vmware"
openstack = "awx_plugins.inventory.plugins:openstack"
rhv = "awx_plugins.inventory.plugins:rhv"
satellite6 = "awx_plugins.inventory.plugins:satellite6"
terraform = "awx_plugins.inventory.plugins:terraform"
controller = "awx_plugins.inventory.plugins:controller"
insights = "awx_plugins.inventory.plugins:insights"
openshift_virtualization = "awx_plugins.inventory.plugins:openshift_virtualization"
constructed = "awx_plugins.inventory.plugins:constructed"

[project.license]
file = "LICENSE"
Expand Down
5 changes: 0 additions & 5 deletions src/awx_plugins/credentials/x/api.py

This file was deleted.

184 changes: 174 additions & 10 deletions tests/importable_test.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,190 @@
"""Smoke tests related to loading entry points."""

from dataclasses import dataclass
from importlib.metadata import entry_points as _discover_entry_points

import pytest

from awx_plugins.inventory.plugins import PluginFileInjector

@pytest.mark.parametrize(
'entry_points_group',
(
'awx.credential_plugins',

@dataclass(frozen=True)
class EntryPointParam:
"""Data structure representing a single exposed plugin."""

group: str
name: str
spec: str

def __str__(self):
"""Render an entry-point parameter as a string.
To be used as a part of parametrized test ID.
"""
return f'{self.name}={self.spec}@{self.group}'


credential_plugins = (
EntryPointParam(
'awx_plugins.credentials',
'aim',
'awx_plugins.credentials.aim:aim_plugin',
),
EntryPointParam(
'awx_plugins.credentials',
'conjur',
'awx_plugins.credentials.conjur:conjur_plugin',
),
EntryPointParam(
'awx_plugins.credentials',
'hashivault_kv',
'awx_plugins.credentials.hashivault:hashivault_kv_plugin',
),
EntryPointParam(
'awx_plugins.credentials',
'hashivault_ssh',
'awx_plugins.credentials.hashivault:hashivault_ssh_plugin',
),
EntryPointParam(
'awx_plugins.credentials',
'azure_kv',
'awx_plugins.credentials.azure_kv:azure_keyvault_plugin',
),
EntryPointParam(
'awx_plugins.credentials',
'centrify_vault_kv',
'awx_plugins.credentials.centrify_vault:centrify_plugin',
),
EntryPointParam(
'awx_plugins.credentials',
'thycotic_dsv',
'awx_plugins.credentials.dsv:dsv_plugin',
),
EntryPointParam(
'awx_plugins.credentials',
'thycotic_tss',
'awx_plugins.credentials.tss:tss_plugin',
),
EntryPointParam(
'awx_plugins.credentials',
'aws_secretsmanager_credential',
'awx_plugins.credentials.aws_secretsmanager:aws_secretmanager_plugin',
),
)
def test_entry_points_exposed(entry_points_group: str) -> None:
"""Verify the plugin entry point is discoverable.


inventory_plugins = (
EntryPointParam(
'awx_plugins.inventory',
'azure-rm',
'awx_plugins.inventory.plugins:azure_rm',
),
EntryPointParam(
'awx_plugins.inventory',
'ec2',
'awx_plugins.inventory.plugins:ec2',
),
EntryPointParam(
'awx_plugins.inventory',
'gce',
'awx_plugins.inventory.plugins:gce',
),
EntryPointParam(
'awx_plugins.inventory',
'vmware',
'awx_plugins.inventory.plugins:vmware',
),
EntryPointParam(
'awx_plugins.inventory',
'openstack',
'awx_plugins.inventory.plugins:openstack',
),
EntryPointParam(
'awx_plugins.inventory',
'rhv',
'awx_plugins.inventory.plugins:rhv',
),
EntryPointParam(
'awx_plugins.inventory',
'satellite6',
'awx_plugins.inventory.plugins:satellite6',
),
EntryPointParam(
'awx_plugins.inventory',
'terraform',
'awx_plugins.inventory.plugins:terraform',
),
EntryPointParam(
'awx_plugins.inventory',
'controller',
'awx_plugins.inventory.plugins:controller',
),
EntryPointParam(
'awx_plugins.inventory',
'insights',
'awx_plugins.inventory.plugins:insights',
),
EntryPointParam(
'awx_plugins.inventory',
'openshift_virtualization',
'awx_plugins.inventory.plugins:openshift_virtualization',
),
EntryPointParam(
'awx_plugins.inventory',
'constructed',
'awx_plugins.inventory.plugins:constructed',
),
)


with_credential_plugins = pytest.mark.parametrize(
'entry_point',
credential_plugins,
ids=str,
)


with_inventory_plugins = pytest.mark.parametrize(
'entry_point',
inventory_plugins,
ids=str,
)


with_all_plugins = pytest.mark.parametrize(
'entry_point',
credential_plugins + inventory_plugins,
ids=str,
)


@with_all_plugins
def test_entry_points_exposed(entry_point: str) -> None:
"""Verify the plugin entry points are discoverable.
This check relies on the plugin-declaring distribution package to be
pre-installed.
"""
entry_points = _discover_entry_points(group=entry_points_group)
assert 'x' in entry_points.names
entry_points = _discover_entry_points(group=entry_point.group)

assert entry_point.name in entry_points.names
assert entry_points[entry_point.name].value == entry_point.spec


@with_credential_plugins
def test_entry_points_are_credential_plugin(entry_point: str) -> None:
"""Ensure all exposed credential plugins are of the same class."""
entry_points = _discover_entry_points(group=entry_point.group)
loaded_plugin_class = entry_points[entry_point.name].load()

loaded_plugin_class_name = type(loaded_plugin_class).__name__
assert loaded_plugin_class_name == 'CredentialPlugin'


assert entry_points['x'].value == 'awx_plugins.credentials.x.api:XPlugin'
@with_inventory_plugins
def test_entry_points_are_inventory_plugin(entry_point: str) -> None:
"""Ensure all exposed inventory plugins are of the same class."""
entry_points = _discover_entry_points(group=entry_point.group)
loaded_plugin_class = entry_points[entry_point.name].load()

assert callable(entry_points['x'].load())
assert issubclass(loaded_plugin_class, PluginFileInjector)

0 comments on commit 60dc36c

Please sign in to comment.