arc42 · vereinfacht · Version 1.0
tina-snow-cli
Spring-Shell-CLI für Anhänge an ServiceNow-KB-Artikeln
Konzeptionelle Kurzfassung der Architektur: Upload, Auflisten und Bereinigung von Anhängen. Grundlage sind der Quellcode (Version 1.0.1), die Konfiguration und die Diagramme dieser Sichten.
Ist-Stand Quellcode-verifiziert
Sichten im Überblick
| Sicht | Diagrammtyp | Inhalt | Seite |
|---|---|---|---|
| Kontext | architecture | Operator, CLI, ServiceNow, Token-Endpunkt; Kapitel „Fachlich“ und „Technisch“ | arc42-kontext |
| Bausteine | architecture | Befehle, Fachkern, Darstellung; Architekturregeln; Sicht „schreibt“ | arc42-bausteine |
| Verteilung | deployment | Stages DEV, QS, PROD; Vertrauensgrenze QS | arc42-verteilung |
| Laufzeit upload | sequence | CSV zu ZIP, Token, sys_id, Upload | arc42-laufzeit-upload |
| Laufzeit cleanup | sequence | Filter, Sortierung, Schleife über zu löschende Anhänge | arc42-laufzeit-cleanup |
| Überblick-Blatt | analog (Whiteboard) | Ein Blatt: Kontext, Bausteine, offene Punkte | analog-arc42-board |
1 Einführung und Ziele
tina-snow-cli ist ein Kommandozeilenwerkzeug auf Basis von Spring Shell. Es hängt Berichte an KB-Artikel in ServiceNow, listet Anhänge auf und bereinigt veraltete Anhänge.
Upload
Bericht per Befehl als Anhang an einen KB-Artikel hängen.
Bereinigung
Anhänge nach Präfix filtern und nur die neuesten n behalten.
Lesbare Ausgabe
Ergebnisse als Tabelle im Terminal, wählbar im Anzug (Theme).
| Stakeholder | Interesse |
|---|---|
| Operator (Redaktion KB, CI-Job) | Befehle zuverlässig ausführen, eindeutige Exit-Codes |
| Entwicklung | Wartbarer Code, aktuelle Dokumentation |
| ServiceNow-Betrieb | Nur definierte REST-Aufrufe, passende Berechtigungen |
| Security | Geschützte Zugangsdaten, kontrollierte Löschungen |
2 Randbedingungen
| Bereich | Vorgabe |
|---|---|
| Technik | Java 21, Spring Boot 4.1.0 (Parent), Spring Shell 4.0.3, Maven |
| Schnittstelle | ServiceNow REST: Table-API kb_knowledge, Attachment-API |
| Zugang | OAuth 2.0 Client Credentials; Zugangsdaten nur über Umgebungsvariablen |
| Stages | DEV, QS, PROD; Basis-URL und Token-Endpunkt je Konfigurationsdatei |
| Betrieb | Standard nicht interaktiv (CI/CD); interaktiver Modus über conf/active-config.yaml |
| Qualitätswerkzeuge | Spotless (Eclipse-Formatter), JaCoCo, CycloneDX-SBOM |
3 Kontextabgrenzung
Die CLI spricht mit vier Partnern: dem Operator, ServiceNow, dem Token-Endpunkt und dem lokalen Dateisystem.
| Nachbar | Kanal | Ausgetauscht |
|---|---|---|
| Operator | Befehlszeile | Befehle, Ausgabe, Exit-Code |
| ServiceNow ITSM | HTTPS, JSON | Artikel-sys_id, Anhangsliste, Upload, Löschung |
| Token-Endpunkt | HTTPS, form-urlencoded | access_token (je Stage verschieden) |
| Dateisystem | lokal | Quelldatei, erzeugtes ZIP |
4 Lösungsstrategie
- Ein Befehl je Anwendungsfall:
upload,read,cleanup;themesteuert die Darstellung. - Alle REST-Aufrufe laufen über
SnowApi. Fehler werden in vier Klassen eingeteilt und auf Exit-Codes abgebildet. - Der Token bleibt im Speicher und wird 30 Sekunden vor Ablauf erneuert. Beim Start holt
AuthWarmupim Hintergrund einen Token. - CSV-Dateien werden vor dem Upload zu ZIP gepackt.
- Abfrage-Strings sind konfigurierbar (Platzhalter
{value}), damit Stages abweichende Felder nutzen können. - Ergebnisse sind ein sealed Modell (
CommandResult). Darstellung (Chrome) und Fachkern sind getrennt.
5 Bausteinsicht
| Baustein | Verantwortung | Pakete |
|---|---|---|
| CLI-Befehle | upload, read, cleanup, theme | snow.attachment, cli |
| Fachkern | Token, Artikelauflösung, Anhänge, REST-Basis, CSV-Kompression | snow, snow.auth, snow.kb, snow.attachment |
| Darstellung | Ergebnis-Rendering, Anzüge, Glyphen, Tabellen, Prompt | render, chrome |
| Konfiguration | ServiceNowProperties, ApiQueryProperties, UiProperties, application.yaml | snow, chrome, resources |
Regeln im Diagramm: Die Darstellung spricht nie direkt mit ServiceNow; Aufrufe laufen nur von oben nach unten (CLI, Fachkern, extern). Beide Regeln sind eingehalten.
Hinweis: Die README beschreibt eine ältere Paketstruktur (config/, service/, UpdateCommand). Maßgeblich ist der Ist-Stand oben.
6 Laufzeitsicht
6.1 Befehl upload
- CSV-Datei wird zu ZIP gepackt. Die ZIP-Datei liegt neben der Quelle.
- Access-Token holen (aus dem Cache oder neu).
- KB-Nummer in sys_id auflösen. Kein Treffer: Exit-Code 3.
- Datei per Multipart an
/api/now/attachment/uploadsenden. - Ergebnis ausgeben: Artikelnummer und Dateiname.
6.2 Befehl cleanup
- Token und sys_id wie beim Upload.
- Anhangsliste des Artikels laden.
- Nach Präfix filtern (Standard
Test) und nachsys_created_onabsteigend sortieren. - Alle Treffer ab Platz n+1 einzeln löschen (Standard n = 3).
- Ergebnis ausgeben: gelöscht und behalten.
6.3 Befehl read
read -a <Nummer> zählt die Anhänge. Mit -A erscheint die Tabelle, mit --raw die vollen sys_ids, Bytes und ISO-Zeitstempel.
7 Verteilungssicht
| Stage | Basis-URL | Token-Endpunkt | Konfiguration |
|---|---|---|---|
| DEV | https://itsm.dev.gematik.solutions | ServiceNow oauth_token.do | conf/dev/active-config.yaml |
| QS | https://itsm.qs.gematik.solutions/ | Microsoft Entra ID (v2.0), eigener Scope | conf/qs/active-config.yaml |
| PROD | https://itsm.gematik.de/ | ServiceNow oauth_token.do | conf/prod/active-config.yaml |
Die Datei conf/active-config.yaml wird beim Start importiert. Sie zeigt aktuell auf QS (siehe R4).
8 Querschnittliche Konzepte
| Thema | Umsetzung |
|---|---|
| Sicherheit | Client Credentials; Secrets über Umgebungsvariablen; Bearer-Token im Header |
| Token-Lebensdauer | expires_in aus der Antwort; ohne Angabe 30 min; Erneuerung 30 s vor Ablauf |
| Fehlerklassen | BadInput, NotFound, AuthFailed, Transport (sealed SnowCliException) |
| Exit-Codes | 1 unerwartet · 2 Eingabe · 3 nicht gefunden · 4 Authentifizierung · 5 Transport |
| Fehlerausgabe | Meldung auf stderr mit Präfix „Fehler:“ |
| Darstellung | Anzüge transit (Standard), atlas, wire; gewählter Anzug wird gespeichert |
| Dateien | Content-Type aus der Dateiendung; CSV zu ZIP über CsvCompressor |
| Logging | Spring-Boot-Logging; Stufen je Paket in der Konfiguration |
9 Entscheidungen
| Nr | Entscheidung | Begründung | Folge |
|---|---|---|---|
| E1 | Spring Shell als Framework | Befehle als Annotationen; interaktiver und nicht interaktiver Modus aus einer Anwendung | Bindung an Spring Shell 4 |
| E2 | OAuth 2.0 Client Credentials | Kein Benutzerlogin, geeignet für CI/CD | Zugangsdaten müssen geschützt verwaltet werden |
| E3 | Konfigurierbare Abfragen (api-query) | Stages mit abweichenden Feldern ohne Codeänderung | Fehlkonfiguration wirkt direkt (R4) |
| E4 | CSV immer zu ZIP | Reduziert das Transfervolumen (laut Klassen-Javadoc) | Weicht von der README-Regel „ab 5 MB“ ab (R9) |
| E5 | Token-Cache im Prozess | Weniger Token-Anfragen je Lauf | Kein Cache über Prozessgrenzen hinweg |
10 Qualitätsanforderungen
| Qualität | Szenario | Stand im Code |
|---|---|---|
| Sicherheit | Zugangsdaten landen nicht im Repository | Nur Umgebungsplatzhalter in application.yaml und conf/*.yaml |
| Automatisierbarkeit | Ein CI-Job wertet den Exit-Code aus | Exit-Codes je Fehlerklasse; Test SnowExitStatusTest |
| Nachvollziehbarkeit | Die Fehlerursache ist aus der Meldung erkennbar | Meldung „Fehler: …“ mit Ursache |
| Wartbarkeit | Ein neuer Befehl braucht keinen Umbau des Fachkerns | Befehle nutzen gemeinsame Services (AuthService, KbClient, AttachmentClient) |
| Prüfbarkeit | Build mit Tests und Coverage | JaCoCo-Report, Surefire-Reports vorhanden |
11 Risiken und technische Schulden
| Nr | Befund | Wirkung | Maßnahme | Status |
|---|---|---|---|---|
| R1 | cleanup verlangt keine Bestätigung; -p ist optional mit Standard „Test“ | Anhänge können ohne Freigabe gelöscht werden | Präfix Pflicht machen; Bestätigung oder Dry-Run ergänzen | Offen |
| R2 | CSV wird immer zu ZIP; die ZIP liegt neben der Quelle und wird ohne Nachfrage überschrieben | Datenverlust bei gleichnamiger ZIP | Zielordner oder Temp-Verzeichnis; Überschreiben verhindern | Offen |
| R3 | Eine Nicht-KB-Eingabe läuft über den Attachment-Lookup und liefert die sys_id eines Anhangs | Falsche Artikel-Zuordnung denkbar | Pfad fachlich klären; Test ergänzen | Zu prüfen |
| R4 | conf/active-config.yaml setzt article auf sys_id=, der KbClient erwartet KB-Nummern; Skriptnamen lauten _dev, die aktive Konfiguration zeigt auf QS | Falsche Stage oder NotFound | Stage-Konfiguration vereinheitlichen; aktive Stage dokumentieren | Zu prüfen |
| R5 | Theme-Name tina in application.yaml existiert nicht | Fällt stillschweigend auf transit zurück | Namen auf transit setzen | Offen |
| R6 | Secret-Variablen sind je Stage unterschiedlich benannt (_QS nur für QS) | Verwechslung, fehlende Zugangsdaten | Einheitliche Namen je Stage | Offen |
| R7 | Root- und Fachlogging auf DEBUG in conf/active-config.yaml | Mehr Log-Inhalt; Inhalte nicht geprüft | Stufe im Profil auf INFO; Logausgaben auf Zugangsdaten prüfen | Zu prüfen |
| R8 | Keine Wiederholung bei Transportfehlern | Ein Netzfehler bricht den Lauf ab | Retry mit Backoff für GET-Aufrufe | Offen |
| R9 | README veraltet (UpdateCommand, Theme-Namen, 5-MB-Regel, Paketstruktur) | Fehlinformation | README an den Ist-Stand angleichen | Offen |
12 Glossar
| Begriff | Bedeutung |
|---|---|
| KB-Artikel | Wissensartikel in ServiceNow (Tabelle kb_knowledge) |
| sys_id | Eindeutige ID eines Datensatzes in ServiceNow |
| Anhang | Datei an einem Datensatz (sys_attachment) |
| Stage | Umgebung: DEV, QS oder PROD |
| Client Credentials | OAuth-Ablauf ohne Benutzer, mit Client-ID und Client-Secret |
| Retain | Anzahl der neuesten Anhänge, die cleanup behält |
| Anzug | Farbschema und Layout der Terminal-Ausgabe (Theme) |
| Chrome | Darstellungsschicht der CLI: Farben, Layout, Tabellen, Prompt |
| Blatt (analog) | Handgezeichnete Skizze im Publisher-Baustein-Stil (Überblick-Blatt) |