Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions sigma/cli/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,19 +155,34 @@ def install_plugin(
default=True,
help="Enable or disable plugin compatibility check.",
)
def upgrade_plugin(compatibility_check: bool):
@click.option(
"--check-pysigma/--no-check-pysigma",
"-l/-L",
default=True,
help="Check after plugin upgrade if pySigma version is still matching the CLI requirement.",
)
def upgrade_plugin(compatibility_check: bool, check_pysigma: bool):
plugins_dir = SigmaPluginDirectory.default_plugin_directory()
for plugin_id in plugins_dir.plugins:
plugin = plugins_dir.get_plugin_by_uuid(uuid=plugin_id)
if plugin.is_installed():
if not compatibility_check or plugin.is_compatible():
if not compatibility_check:
plugin.upgrade()
click.echo(f"Successfully upgrade plugin '{plugin.id}'")
elif plugin.is_compatible():
# Install the newest release that is compatible with the installed pySigma version
# instead of an unpinned upgrade to the newest release, which might require
# another pySigma version.
plugin.install()
click.echo(f"Successfully upgrade plugin '{plugin.id}'")
else:
click.echo(
f"Plugin '{plugin.id}' not compatible with installed pySigma version"
)

if check_pysigma:
check_pysigma_command()
Comment on lines +183 to +184


@plugin_group.command(name="uninstall", help="Uninstall plugin by identifier or UUID.")
@click.option("--uuid", "-u", is_flag=True, help="Uninstall plugin by UUID.")
Expand Down
73 changes: 73 additions & 0 deletions tests/test_plugin.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import pytest
from click.testing import CliRunner

import sigma.cli.plugin
import sigma.plugins
from sigma.cli.plugin import (
plugin_group,
list_plugins,
install_plugin,
uninstall_plugin,
upgrade_plugin,
)
from sigma.plugins import SigmaPlugin, SigmaPluginDirectory


def test_plugin_help():
Expand Down Expand Up @@ -110,3 +115,71 @@ def test_plugin_uninstall():
result = cli.invoke(uninstall_plugin, ["splunk"])
assert result.exit_code == 0
assert "Successfully uninstalled" in result.output


@pytest.fixture
def stubbed_plugin(monkeypatch):
"""
An installed plugin with two releases on (stubbed) PyPI: 1.0.0 is compatible with the installed
pySigma 1.x, 2.0.0 requires pySigma 2.x. pip calls and the pySigma check are recorded.
"""
requirements = {
"1.0.0": ["pysigma (>=1.0.0,<2.0.0)"],
"2.0.0": ["pysigma (>=2.0.0,<3.0.0)"],
}

def fake_pypi_json(package, version=None):
if version is None:
return {"releases": {v: [{"file": 1}] for v in requirements}}
return {"info": {"requires_dist": requirements[version]}}

plugin = SigmaPlugin.from_dict(
{
"uuid": "00000000-0000-4000-8000-000000000001",
"type": "backend",
"id": "demo",
"description": "demo",
"package": "pysigma-backend-demo",
"project-url": "https://example.invalid",
"report-issue-url": "https://example.invalid",
"state": "stable",
"pysigma-version": ">=0.1",
}
)
directory = SigmaPluginDirectory()
directory.register_plugin(plugin)

calls = {"pip": [], "check_pysigma": 0}

def fake_check_call(cmd, *args, **kwargs):
calls["pip"].append(cmd[cmd.index("install") + 1 :])

def fake_check_pysigma():
calls["check_pysigma"] += 1

monkeypatch.setattr(sigma.plugins.SigmaPlugin, "_get_pypi_json", staticmethod(fake_pypi_json))
monkeypatch.setattr(sigma.plugins.SigmaPlugin, "is_installed", lambda self: True)
monkeypatch.setattr(sigma.plugins.subprocess, "check_call", fake_check_call)
monkeypatch.setattr(
sigma.cli.plugin.SigmaPluginDirectory, "default_plugin_directory", lambda *a, **k: directory
)
monkeypatch.setattr(sigma.cli.plugin, "check_pysigma_command", fake_check_pysigma)
return calls


def test_plugin_upgrade_installs_compatible_release(stubbed_plugin):
cli = CliRunner()
result = cli.invoke(upgrade_plugin, [])
assert result.exit_code == 0
assert "Successfully upgrade plugin 'demo'" in result.output
assert stubbed_plugin["pip"][-1][-1] == "pysigma-backend-demo==1.0.0"
assert stubbed_plugin["check_pysigma"] == 1


def test_plugin_upgrade_without_compatibility_check(stubbed_plugin):
cli = CliRunner()
result = cli.invoke(upgrade_plugin, ["--no-compatibility-check", "--no-check-pysigma"])
assert result.exit_code == 0
assert "--upgrade" in stubbed_plugin["pip"][-1]
assert stubbed_plugin["pip"][-1][-1] == "pysigma-backend-demo"
assert stubbed_plugin["check_pysigma"] == 0