74 lines
2.9 KiB
Python
74 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
from django import forms
|
|
|
|
from .client import CatalogPlugin
|
|
from .runtime import RuntimeSettings
|
|
|
|
|
|
class LifecycleConfirmForm(forms.Form):
|
|
confirmation = forms.CharField(
|
|
max_length=64,
|
|
label="Plugin-Slug zur Bestätigung",
|
|
help_text="Diese Eingabe verhindert versehentliche Lifecycle-Aktionen.",
|
|
)
|
|
version = forms.ChoiceField(required=False, label="Version")
|
|
dry_run = forms.BooleanField(
|
|
required=False,
|
|
initial=True,
|
|
label="Nur prüfen (Dry-Run)",
|
|
help_text="Plant und validiert den Vorgang, ohne Dateien oder Prozesse zu verändern.",
|
|
)
|
|
|
|
def __init__(
|
|
self,
|
|
*args,
|
|
plugin: CatalogPlugin,
|
|
action: str,
|
|
runtime: RuntimeSettings,
|
|
**kwargs,
|
|
):
|
|
super().__init__(*args, **kwargs)
|
|
self.plugin = plugin
|
|
self.action = action
|
|
self.runtime = runtime
|
|
self.fields["confirmation"].widget.attrs.update({"autocomplete": "off", "placeholder": plugin.slug})
|
|
self.fields["dry_run"].initial = runtime.default_dry_run
|
|
self.has_installable_release = True
|
|
if action in {"install", "update"}:
|
|
choices = [
|
|
(release.version, release.version)
|
|
for release in plugin.installable_releases(
|
|
runtime.netbox_version,
|
|
require_approval_marker=runtime.execution_mode == "agent",
|
|
)
|
|
]
|
|
choices.sort(reverse=True)
|
|
self.fields["version"].choices = choices
|
|
self.has_installable_release = bool(choices)
|
|
self.fields["version"].required = self.has_installable_release
|
|
self.fields["version"].disabled = not self.has_installable_release
|
|
self.fields["version"].initial = plugin.latest_version
|
|
else:
|
|
self.fields.pop("version")
|
|
for field in self.fields.values():
|
|
if not isinstance(field.widget, forms.CheckboxInput):
|
|
field.widget.attrs.setdefault("class", "form-control")
|
|
|
|
def clean_confirmation(self) -> str:
|
|
value = self.cleaned_data["confirmation"]
|
|
if value != self.plugin.slug:
|
|
raise forms.ValidationError("Der Slug stimmt nicht exakt überein.")
|
|
return value
|
|
|
|
def clean(self):
|
|
cleaned = super().clean()
|
|
if self.action in {"install", "update"} and not self.has_installable_release:
|
|
raise forms.ValidationError(
|
|
"Keine freigegebene, kompatible Plugin-Version ist verfügbar. "
|
|
"Das Source-Artefakt muss zunächst im Store synchronisiert und freigegeben werden."
|
|
)
|
|
if self.runtime.execution_mode == "dry_run" and not cleaned.get("dry_run", False):
|
|
self.add_error("dry_run", "Reale Aktionen sind in execution_mode=dry_run deaktiviert.")
|
|
return cleaned
|