mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 13:01:56 +00:00
fix(sdk): honor from_cli_args return value in init_global_provider fallback
This commit is contained in:
@@ -146,7 +146,13 @@ class Provider(ABC):
|
||||
|
||||
@classmethod
|
||||
def from_cli_args(cls, arguments: Namespace, fixer_config: dict) -> "Provider":
|
||||
"""Instantiate the provider from CLI arguments."""
|
||||
"""Instantiate the provider from CLI arguments and return the instance.
|
||||
|
||||
The caller wires the returned instance into the global provider slot
|
||||
via Provider.set_global_provider(). Implementations that already call
|
||||
set_global_provider(self) from __init__ are also supported — the call
|
||||
site tolerates a None return in that case.
|
||||
"""
|
||||
raise NotImplementedError(f"{cls.__name__} has not implemented from_cli_args()")
|
||||
|
||||
def get_output_options(self, arguments, bulk_checks_metadata):
|
||||
@@ -507,8 +513,17 @@ class Provider(ABC):
|
||||
fixer_config=fixer_config,
|
||||
)
|
||||
else:
|
||||
# Dynamic fallback: any external/custom provider
|
||||
provider_class.from_cli_args(arguments, fixer_config)
|
||||
# Dynamic fallback: any external/custom provider.
|
||||
# Honor the from_cli_args type hint (-> Provider): if the
|
||||
# implementation returns an instance, wire it as the global
|
||||
# provider here. Implementations that call
|
||||
# set_global_provider(self) from __init__ return None and
|
||||
# remain supported (the condition below is a no-op for them).
|
||||
provider_instance = provider_class.from_cli_args(
|
||||
arguments, fixer_config
|
||||
)
|
||||
if provider_instance is not None:
|
||||
Provider.set_global_provider(provider_instance)
|
||||
|
||||
except TypeError as error:
|
||||
logger.critical(
|
||||
|
||||
@@ -145,6 +145,41 @@ class FakeToolWrapperProvider(Provider):
|
||||
pass
|
||||
|
||||
|
||||
class FakePureContractProvider(Provider):
|
||||
"""External provider that honors the from_cli_args type hint literally:
|
||||
returns an instance without calling Provider.set_global_provider() from
|
||||
__init__. Used to verify the call site wires the returned instance."""
|
||||
|
||||
_type = "fakepure"
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self._type
|
||||
|
||||
@property
|
||||
def identity(self):
|
||||
return MagicMock(host_id="fake-pure-1")
|
||||
|
||||
@property
|
||||
def session(self):
|
||||
return MagicMock()
|
||||
|
||||
@property
|
||||
def audit_config(self):
|
||||
return {}
|
||||
|
||||
def setup_session(self):
|
||||
return MagicMock()
|
||||
|
||||
def print_credentials(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def from_cli_args(cls, arguments, fixer_config):
|
||||
# Literal contract: return the instance, no side-effect in __init__.
|
||||
return cls()
|
||||
|
||||
|
||||
class FakeProviderNoHelpText(Provider):
|
||||
"""Provider without _cli_help_text."""
|
||||
|
||||
@@ -439,6 +474,31 @@ class TestProviderInitialization:
|
||||
with pytest.raises(SystemExit):
|
||||
Provider.init_global_provider(args)
|
||||
|
||||
@patch("prowler.providers.common.provider.load_and_validate_config_file")
|
||||
@patch("prowler.providers.common.provider.Provider._load_ep_provider")
|
||||
@patch("prowler.providers.common.provider.import_module")
|
||||
def test_init_global_provider_wires_instance_returned_by_from_cli_args(
|
||||
self, mock_import, mock_load_ep, mock_config
|
||||
):
|
||||
"""A provider that implements from_cli_args as a pure function (returns
|
||||
the instance without calling set_global_provider from __init__) is
|
||||
correctly wired as the global provider by init_global_provider."""
|
||||
mock_import.side_effect = ImportError("No built-in")
|
||||
mock_load_ep.return_value = FakePureContractProvider
|
||||
mock_config.return_value = {}
|
||||
|
||||
args = Namespace(
|
||||
provider="fakepure",
|
||||
fixer_config="config.yaml",
|
||||
config_file="config.yaml",
|
||||
)
|
||||
|
||||
Provider._global = None
|
||||
Provider.init_global_provider(args)
|
||||
|
||||
assert isinstance(Provider._global, FakePureContractProvider)
|
||||
Provider._global = None
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
# 3. Check Discovery
|
||||
|
||||
Reference in New Issue
Block a user