Merge branch 'main' of https://git.local.unique-studios.de/PowerShell-Projekte/DSC-Configuration-Compiler
This commit is contained in:
3979
Compiler.ps1
3979
Compiler.ps1
File diff suppressed because it is too large
Load Diff
@@ -1,89 +0,0 @@
|
|||||||
function Import-OrderedPowerShellDataFile {
|
|
||||||
param(
|
|
||||||
[Parameter(Mandatory)]
|
|
||||||
[string]$Path
|
|
||||||
)
|
|
||||||
|
|
||||||
function ConvertTo-OrderedHashtable {
|
|
||||||
param(
|
|
||||||
$HashtableAst
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verwende OrderedDictionary statt [ordered]@{}
|
|
||||||
$ordered = New-Object System.Collections.Specialized.OrderedDictionary
|
|
||||||
|
|
||||||
# Sortiere KeyValuePairs nach ihrer Position im Quelltext
|
|
||||||
$sortedKvps = $HashtableAst.KeyValuePairs | Sort-Object { $_.Item1.Extent.StartOffset }
|
|
||||||
|
|
||||||
foreach ($kvp in $sortedKvps) {
|
|
||||||
# Schlüssel extrahieren
|
|
||||||
$key = $kvp.Item1.Extent.Text -replace '[''"]', ''
|
|
||||||
|
|
||||||
# Wert verarbeiten
|
|
||||||
$valueAst = $kvp.Item2
|
|
||||||
|
|
||||||
# Suche nach HashtableAst in PipelineAst
|
|
||||||
$hashtable = $null
|
|
||||||
if ($valueAst -is [System.Management.Automation.Language.HashtableAst]) {
|
|
||||||
$hashtable = $valueAst
|
|
||||||
}
|
|
||||||
elseif ($valueAst -is [System.Management.Automation.Language.PipelineAst]) {
|
|
||||||
# Suche HashtableAst innerhalb der Pipeline
|
|
||||||
$hashtable = $valueAst.Find({
|
|
||||||
$args[0] -is [System.Management.Automation.Language.HashtableAst]
|
|
||||||
}, $false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($hashtable) {
|
|
||||||
$value = ConvertTo-OrderedHashtable -HashtableAst $hashtable
|
|
||||||
}
|
|
||||||
elseif ($valueAst -is [System.Management.Automation.Language.ArrayLiteralAst]) {
|
|
||||||
$value = @()
|
|
||||||
foreach ($element in $valueAst.Elements) {
|
|
||||||
if ($element -is [System.Management.Automation.Language.HashtableAst]) {
|
|
||||||
$value += ConvertTo-OrderedHashtable -HashtableAst $element
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$value += Invoke-Expression $element.Extent.Text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
$value = Invoke-Expression $valueAst.Extent.Text
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
$value = $valueAst.Extent.Text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$ordered.Add($key, $value)
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ordered
|
|
||||||
}
|
|
||||||
|
|
||||||
# Datei parsen
|
|
||||||
$errors = $null
|
|
||||||
$tokens = $null
|
|
||||||
$ast = [System.Management.Automation.Language.Parser]::ParseFile(
|
|
||||||
$Path,
|
|
||||||
[ref]$tokens,
|
|
||||||
[ref]$errors
|
|
||||||
)
|
|
||||||
|
|
||||||
if ($errors) {
|
|
||||||
throw "Fehler beim Parsen der Datei: $($errors[0].Message)"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Finde die oberste Hashtable
|
|
||||||
$hashtableAst = $ast.Find({
|
|
||||||
$args[0] -is [System.Management.Automation.Language.HashtableAst]
|
|
||||||
}, $true)
|
|
||||||
|
|
||||||
if (-not $hashtableAst) {
|
|
||||||
throw "Keine Hashtable in der Datei gefunden"
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConvertTo-OrderedHashtable -HashtableAst $hashtableAst
|
|
||||||
}
|
|
||||||
@@ -10,10 +10,11 @@ function Merge-Templates {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
$TemplateData = Import-OrderedPowerShellDataFile -Path $file -ErrorAction Stop
|
$TemplateData = [TemplateBuilder]::new($file).Template
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
$Errors += "Datei konnte nicht importiert werden"
|
$Errors += "Datei konnte nicht importiert werden"
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
$ConfigurationData = Merge-ConfigurationData -Template $ConfigurationData -Deployment $TemplateData
|
$ConfigurationData = Merge-ConfigurationData -Template $ConfigurationData -Deployment $TemplateData
|
||||||
|
|||||||
185
README.md
Normal file
185
README.md
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
# DSC Configuration Compiler
|
||||||
|
|
||||||
|
Ein WinForms-basiertes PowerShell-Tool zum Laden, Kombinieren, Anzeigen und Exportieren von DSC-nahen Konfigurationen auf Basis von `psd1`-Dateien.
|
||||||
|
|
||||||
|
Der Fokus des Projekts liegt auf einem einfachen Template-Workflow:
|
||||||
|
|
||||||
|
- Templates aus Ordnern laden
|
||||||
|
- mehrere Templates zu einer Zielkonfiguration zusammenfuehren
|
||||||
|
- Parameter und Variablen aufloesen
|
||||||
|
- die resultierende Struktur im TreeView pruefen
|
||||||
|
- die zusammengefuehrte Konfiguration wieder als `psd1` exportieren
|
||||||
|
|
||||||
|
## Voraussetzungen
|
||||||
|
|
||||||
|
- Windows
|
||||||
|
- PowerShell mit WinForms-Unterstuetzung
|
||||||
|
- Schreibzugriff auf `%APPDATA%`
|
||||||
|
|
||||||
|
Das Tool speichert Einstellungen und Logs unterhalb von `%APPDATA%\DSC Tool`.
|
||||||
|
|
||||||
|
## Start
|
||||||
|
|
||||||
|
Das Projekt kann direkt ueber `Compiler.ps1` gestartet werden:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
powershell -ExecutionPolicy Bypass -File .\Compiler.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternativ:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
pwsh -File .\Compiler.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Projektstruktur
|
||||||
|
|
||||||
|
```text
|
||||||
|
.
|
||||||
|
|-- Compiler.ps1
|
||||||
|
|-- Functions/
|
||||||
|
|-- Templates/
|
||||||
|
`-- Deployments/
|
||||||
|
```
|
||||||
|
|
||||||
|
- `Compiler.ps1`: Hauptanwendung, UI, Parser- und Resolver-Logik
|
||||||
|
- `Functions/`: zusaetzliche Funktionen fuer Import, Export, Merge und UI-Aktualisierung
|
||||||
|
- `Templates/`: wiederverwendbare Konfigurationsbausteine
|
||||||
|
- `Deployments/`: exportierte oder vorbereitete Zielkonfigurationen
|
||||||
|
|
||||||
|
## Bedienung
|
||||||
|
|
||||||
|
1. Anwendung starten.
|
||||||
|
2. Falls noetig ueber `Einstellungen -> Ordner waehlen...` den Root-Ordner setzen.
|
||||||
|
3. Templates aus den Kategorien laden.
|
||||||
|
4. Gewuenschte Templates per Doppelklick zur Auswahl hinzufuegen.
|
||||||
|
5. Die Auswahl zusammenfuehren.
|
||||||
|
6. Das Ergebnis im TreeView pruefen.
|
||||||
|
7. Die zusammengefuehrte Konfiguration als `psd1` exportieren.
|
||||||
|
|
||||||
|
Import und Export werden ueber den Deployment-Ordner abgewickelt.
|
||||||
|
|
||||||
|
## Template-Modell
|
||||||
|
|
||||||
|
Templates bestehen aus drei optionalen Hauptbereichen:
|
||||||
|
|
||||||
|
- `Parameters`
|
||||||
|
- `Variables`
|
||||||
|
- `Resources`
|
||||||
|
|
||||||
|
Ein vereinfachtes Beispiel:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
@{
|
||||||
|
Parameters = @{
|
||||||
|
DatabasePrefix = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = 'SP'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Variables = @{
|
||||||
|
ConfigDbName = "[concat(parameters('DatabasePrefix'),'_','Farm_Config')]"
|
||||||
|
}
|
||||||
|
|
||||||
|
Resources = @{
|
||||||
|
NonNodeData = @{
|
||||||
|
Services = @{
|
||||||
|
Example = @{
|
||||||
|
DatabaseName = "[variables('ConfigDbName')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ausdruckssyntax
|
||||||
|
|
||||||
|
Die Auswertung ist ARM-inspiriert. Template-Ausdruecke stehen in eckigen Klammern:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
"[concat(parameters('Prefix'),'_','Database')]"
|
||||||
|
```
|
||||||
|
|
||||||
|
Unterstuetzte Referenzen:
|
||||||
|
|
||||||
|
- `parameters('Name')`
|
||||||
|
- `variables('Name')`
|
||||||
|
|
||||||
|
Zusaetzlich werden aus Rueckwaertskompatibilitaet auch diese Varianten verstanden:
|
||||||
|
|
||||||
|
- `Parameter('Name')`
|
||||||
|
- `Variable('Name')`
|
||||||
|
|
||||||
|
Unterstuetzte Funktionen:
|
||||||
|
|
||||||
|
- `concat(...)`
|
||||||
|
- `toLower(...)`
|
||||||
|
- `toUpper(...)`
|
||||||
|
- `substring(...)`
|
||||||
|
- `replace(...)`
|
||||||
|
- `indexOf(...)`
|
||||||
|
- `firstIndexOf(...)`
|
||||||
|
- `lastIndexOf(...)`
|
||||||
|
|
||||||
|
Funktionsnamen werden ohne freie PowerShell-Ausfuehrung ausgewertet. Die `psd1`-Dateien werden als Daten geparst, nicht als beliebiger Script-Code interpretiert.
|
||||||
|
|
||||||
|
## Aufloesungsreihenfolge
|
||||||
|
|
||||||
|
Die Aufloesung erfolgt in dieser Reihenfolge:
|
||||||
|
|
||||||
|
1. Parameterwerte und Defaultwerte
|
||||||
|
2. Variablen
|
||||||
|
3. Ressourcenwerte
|
||||||
|
|
||||||
|
Zirkulaere Variablenreferenzen werden erkannt und als Fehler behandelt.
|
||||||
|
|
||||||
|
## Merge-Verhalten
|
||||||
|
|
||||||
|
Beim Zusammenfuehren mehrerer Templates werden vorhandene Eintraege rekursiv kombiniert:
|
||||||
|
|
||||||
|
- Hashtables werden rekursiv gemerged
|
||||||
|
- Arrays werden anhand passender Name-Felder zusammengefuehrt
|
||||||
|
- fehlende Werte aus Templates werden in das Ergebnis uebernommen
|
||||||
|
|
||||||
|
Die finale Anzeige im TreeView basiert auf dem zusammengefuehrten und bereits aufgeloesten Modell.
|
||||||
|
|
||||||
|
## Export
|
||||||
|
|
||||||
|
Der Export schreibt die aktuelle TreeView-Struktur wieder in eine `psd1`-Datei.
|
||||||
|
|
||||||
|
Standardziel beim Speichern ist:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Deployments\merged_config.psd1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Hinweise
|
||||||
|
|
||||||
|
- Einstellungen werden benutzerbezogen gespeichert.
|
||||||
|
- Logs werden pro Tag unter `%APPDATA%\DSC Tool\Logs` geschrieben.
|
||||||
|
- Templates sollten deklarativ bleiben und nur Daten plus Template-Ausdruecke enthalten.
|
||||||
|
- Fuer neue Templates wird die ARM-aehnliche Syntax mit `parameters()` und `variables()` empfohlen.
|
||||||
|
|
||||||
|
## Beispielinhalt
|
||||||
|
|
||||||
|
Im Repository ist bereits ein groesseres Beispiel enthalten:
|
||||||
|
|
||||||
|
- `Templates\Service\SharePointServer.psd1`
|
||||||
|
|
||||||
|
Dieses Template zeigt die Verwendung von:
|
||||||
|
|
||||||
|
- Parametern
|
||||||
|
- Variablen
|
||||||
|
- verschachtelten Ressourcen
|
||||||
|
- String-Funktionen wie `concat()` und `substring()`
|
||||||
|
|
||||||
|
## Weiterentwicklung
|
||||||
|
|
||||||
|
Sinnvolle naechste Schritte fuer das Projekt sind:
|
||||||
|
|
||||||
|
- Tests fuer Parser, Resolver und Merge-Verhalten
|
||||||
|
- typsicherer Export-Roundtrip
|
||||||
|
- robustere Initialisierung der Pfade und Settings
|
||||||
|
- weitere Template-Funktionen nach Bedarf
|
||||||
Reference in New Issue
Block a user