Compare commits
6 Commits
01a535eb39
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a4ba96dc8 | ||
|
|
6986570510 | ||
|
|
846dccf468 | ||
| 7dd71be14c | |||
| f5dcc022cf | |||
| 5a57021e6a |
3616
Compiler.Core.ps1
Normal file
3616
Compiler.Core.ps1
Normal file
File diff suppressed because it is too large
Load Diff
3824
Compiler.ps1
3824
Compiler.ps1
File diff suppressed because it is too large
Load Diff
@@ -1,93 +0,0 @@
|
|||||||
@{
|
|
||||||
Resources = @{
|
|
||||||
NonNodeData = @{
|
|
||||||
Services = @{
|
|
||||||
SharePoint = @{
|
|
||||||
Farm = @{
|
|
||||||
Passphrase = 'Use-SecureString-Or-KeyVault'
|
|
||||||
ConfigDatabaseName = 'SharePoint_Farm_Config'
|
|
||||||
ServiceApplications = @{
|
|
||||||
AppManagementService = @{
|
|
||||||
DatabaseName = 'SharePoint_Services_AppManagement'
|
|
||||||
Provision = 'True'
|
|
||||||
}
|
|
||||||
StateService = @{
|
|
||||||
DatabaseName = 'SharePoint_Services_StateService'
|
|
||||||
Provision = 'True'
|
|
||||||
}
|
|
||||||
SubscriptionSettingsService = @{
|
|
||||||
DatabaseName = 'SharePoint_Services_SubscriptionSettings'
|
|
||||||
Provision = 'True'
|
|
||||||
}
|
|
||||||
ManagedMetadataService = @{
|
|
||||||
DatabaseName = 'SharePoint_Services_ManagedMetadata'
|
|
||||||
Name = 'Managed Metadata Service'
|
|
||||||
ApplicationPool = 'SharePoint Service Applications'
|
|
||||||
Provision = 'True'
|
|
||||||
}
|
|
||||||
SearchService = @{
|
|
||||||
DatabaseName = 'SharePoint_Services_Search'
|
|
||||||
Name = 'Search Service Application'
|
|
||||||
ApplicationPool = 'SharePoint Service Applications'
|
|
||||||
Provision = 'True'
|
|
||||||
}
|
|
||||||
UsageAndHealthService = @{
|
|
||||||
DatabaseName = 'SharePoint_Services_UsageAndHealth'
|
|
||||||
Provision = 'True'
|
|
||||||
}
|
|
||||||
SecureStoreService = @{
|
|
||||||
DatabaseName = 'SharePoint_Services_SecureStore'
|
|
||||||
Name = 'Secure Store Service'
|
|
||||||
ApplicationPool = 'SharePoint Service Applications'
|
|
||||||
Provision = 'True'
|
|
||||||
}
|
|
||||||
UserProfileService = @{
|
|
||||||
SyncDBName = 'SharePoint_Services_UserProfile_SyncDB'
|
|
||||||
ApplicationPool = 'SharePoint User Profile Services'
|
|
||||||
Provision = 'True'
|
|
||||||
Name = 'User Profile Service'
|
|
||||||
SocialDBName = 'SharePoint_Services_UserProfile_SocialDB'
|
|
||||||
ProfileDBName = 'SharePoint_Services_UserProfile_ProfileDB'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CentralAdminAuth = 'NTLM'
|
|
||||||
CentralAdminPort = '2016'
|
|
||||||
AdminContentDatabase = 'SharePoint_Farm_AdminContent'
|
|
||||||
ServiceApplicationPools = @{
|
|
||||||
Default = @{
|
|
||||||
Account = 'CONTOSO\sp_services'
|
|
||||||
Name = 'SharePoint Service Applications'
|
|
||||||
}
|
|
||||||
UserProfile = @{
|
|
||||||
Account = 'CONTOSO\sp_ups'
|
|
||||||
Name = 'SharePoint User Profile Services'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Database = @{
|
|
||||||
SQLAlias = @{
|
|
||||||
SQLServer = @{
|
|
||||||
InstanceName = ''
|
|
||||||
ServerName = ''
|
|
||||||
TcpPort = '0'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
General = @{
|
|
||||||
ProductKey = '0000-0000-0000-0000-0000'
|
|
||||||
}
|
|
||||||
Windows = @{
|
|
||||||
Registry = @{
|
|
||||||
DisableLoopbackCheck = @{
|
|
||||||
Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa'
|
|
||||||
Name = 'DisableLoopbackCheck'
|
|
||||||
Value = '1'
|
|
||||||
Type = 'DWord'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,8 +10,9 @@ function Export-ConfigurationData {
|
|||||||
)
|
)
|
||||||
if ($result.Result) {
|
if ($result.Result) {
|
||||||
try {
|
try {
|
||||||
$ConfigurationData = @{
|
$ConfigurationData = $script:ResolvedConfigurationData
|
||||||
"Resources" = $(ConvertFrom-TreeView -TreeView $treeView -SkipRootNode)
|
if($null -eq $ConfigurationData){
|
||||||
|
throw "Keine aufgelöste ConfigurationData zum Exportieren vorhanden."
|
||||||
}
|
}
|
||||||
|
|
||||||
Export-Hashtable -Hashtable $ConfigurationData -Path $result.FileName
|
Export-Hashtable -Hashtable $ConfigurationData -Path $result.FileName
|
||||||
|
|||||||
170
Functions/Get-TemplatePreviewData.ps1
Normal file
170
Functions/Get-TemplatePreviewData.ps1
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
function Get-TemplatePreviewData {
|
||||||
|
[CmdletBinding()]
|
||||||
|
Param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]
|
||||||
|
$TemplatePath
|
||||||
|
)
|
||||||
|
|
||||||
|
if (-not (Test-Path -Path $TemplatePath -PathType Leaf)) {
|
||||||
|
throw "Template nicht gefunden: $TemplatePath"
|
||||||
|
}
|
||||||
|
|
||||||
|
$directory = Split-Path -Path $TemplatePath -Parent
|
||||||
|
$defaultFiles = @(Get-ChildItem -Path $directory -Filter "*.psd1" -File -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object { $_.BaseName -eq "Default" -or $_.BaseName -like "*.Default" } |
|
||||||
|
Sort-Object Name)
|
||||||
|
|
||||||
|
$mergeFiles = @()
|
||||||
|
$mergeFiles += @($defaultFiles | ForEach-Object { $_.FullName })
|
||||||
|
$mergeFiles += $TemplatePath
|
||||||
|
$mergedConfigurationData = $null
|
||||||
|
|
||||||
|
foreach ($file in $mergeFiles) {
|
||||||
|
$templateData = Import-PowerShellDataFile -Path $file -ErrorAction Stop
|
||||||
|
|
||||||
|
if ($null -eq $mergedConfigurationData) {
|
||||||
|
$mergedConfigurationData = $templateData
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$mergedConfigurationData = Merge-DSCConfigurationData -Template $mergedConfigurationData -Deployment $templateData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$resolvedConfigurationData = $null
|
||||||
|
$resolveError = $null
|
||||||
|
|
||||||
|
try {
|
||||||
|
$resolvedConfigurationData = Resolve-DSCConfigurationData -ConfigurationData $mergedConfigurationData -ErrorAction Stop
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$resolveError = $_
|
||||||
|
}
|
||||||
|
|
||||||
|
$displayOrder = $null
|
||||||
|
if (Get-Command -Name Import-OrderedPowerShellDataFile -ErrorAction SilentlyContinue) {
|
||||||
|
foreach ($file in $mergeFiles) {
|
||||||
|
$orderedTemplateData = Import-OrderedPowerShellDataFile -Path $file -ErrorAction Stop
|
||||||
|
|
||||||
|
if ($null -eq $displayOrder) {
|
||||||
|
$displayOrder = $orderedTemplateData
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$displayOrder = Merge-TemplatePreviewOrder -Base $displayOrder -Override $orderedTemplateData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$displaySource = if ($null -ne $resolvedConfigurationData) { $resolvedConfigurationData } else { $mergedConfigurationData }
|
||||||
|
$displayConfigurationData = ConvertTo-TemplatePreviewDisplayOrder -Value $displaySource -Order $displayOrder
|
||||||
|
|
||||||
|
[PSCustomObject]@{
|
||||||
|
Files = $mergeFiles
|
||||||
|
Merged = $mergedConfigurationData
|
||||||
|
Resolved = $resolvedConfigurationData
|
||||||
|
Display = $displayConfigurationData
|
||||||
|
ResolveError = $resolveError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-TemplatePreviewDictionaryKey {
|
||||||
|
Param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[System.Collections.IDictionary]
|
||||||
|
$Dictionary,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]
|
||||||
|
$Key
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($Dictionary -is [System.Collections.Specialized.OrderedDictionary]) {
|
||||||
|
return $Dictionary.Contains($Key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return $Dictionary.ContainsKey($Key)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Merge-TemplatePreviewOrder {
|
||||||
|
Param(
|
||||||
|
[AllowNull()]
|
||||||
|
$Base,
|
||||||
|
|
||||||
|
[AllowNull()]
|
||||||
|
$Override
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($Base -is [System.Collections.IDictionary] -and $Override -is [System.Collections.IDictionary]) {
|
||||||
|
$ordered = New-Object System.Collections.Specialized.OrderedDictionary
|
||||||
|
|
||||||
|
foreach ($key in $Base.Keys) {
|
||||||
|
if (Test-TemplatePreviewDictionaryKey -Dictionary $Override -Key $key) {
|
||||||
|
$ordered.Add($key, (Merge-TemplatePreviewOrder -Base $Base[$key] -Override $Override[$key]))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$ordered.Add($key, $Base[$key])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($key in $Override.Keys) {
|
||||||
|
if (-not (Test-TemplatePreviewDictionaryKey -Dictionary $ordered -Key $key)) {
|
||||||
|
$ordered.Add($key, $Override[$key])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ordered
|
||||||
|
}
|
||||||
|
|
||||||
|
return $Override
|
||||||
|
}
|
||||||
|
|
||||||
|
function ConvertTo-TemplatePreviewDisplayOrder {
|
||||||
|
Param(
|
||||||
|
[AllowNull()]
|
||||||
|
$Value,
|
||||||
|
|
||||||
|
[AllowNull()]
|
||||||
|
$Order
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($Value -is [System.Collections.IDictionary]) {
|
||||||
|
$ordered = New-Object System.Collections.Specialized.OrderedDictionary
|
||||||
|
$orderedKeys = @()
|
||||||
|
|
||||||
|
if ($Order -is [System.Collections.IDictionary]) {
|
||||||
|
foreach ($key in $Order.Keys) {
|
||||||
|
if (Test-TemplatePreviewDictionaryKey -Dictionary $Value -Key $key) {
|
||||||
|
$orderedKeys += $key
|
||||||
|
$ordered.Add($key, (ConvertTo-TemplatePreviewDisplayOrder -Value $Value[$key] -Order $Order[$key]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($key in $Value.Keys) {
|
||||||
|
if ($orderedKeys -notcontains $key) {
|
||||||
|
$ordered.Add($key, (ConvertTo-TemplatePreviewDisplayOrder -Value $Value[$key] -Order $null))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ordered
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Value -is [System.Collections.IEnumerable] -and -not ($Value -is [string])) {
|
||||||
|
$items = @()
|
||||||
|
$index = 0
|
||||||
|
|
||||||
|
foreach ($item in $Value) {
|
||||||
|
$itemOrder = $null
|
||||||
|
if ($Order -is [System.Array] -and $Order.Count -gt $index) {
|
||||||
|
$itemOrder = $Order[$index]
|
||||||
|
}
|
||||||
|
|
||||||
|
$items += ,(ConvertTo-TemplatePreviewDisplayOrder -Value $item -Order $itemOrder)
|
||||||
|
$index++
|
||||||
|
}
|
||||||
|
|
||||||
|
return ,$items
|
||||||
|
}
|
||||||
|
|
||||||
|
return $Value
|
||||||
|
}
|
||||||
@@ -1,89 +1,117 @@
|
|||||||
function Import-OrderedPowerShellDataFile {
|
function Import-OrderedPowerShellDataFile {
|
||||||
param(
|
[CmdletBinding()]
|
||||||
[Parameter(Mandatory)]
|
Param(
|
||||||
[string]$Path
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]
|
||||||
|
$Path
|
||||||
)
|
)
|
||||||
|
|
||||||
function ConvertTo-OrderedHashtable {
|
function ConvertTo-OrderedHashtable {
|
||||||
param(
|
Param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
$HashtableAst
|
$HashtableAst
|
||||||
)
|
)
|
||||||
|
|
||||||
# Verwende OrderedDictionary statt [ordered]@{}
|
$Ordered = New-Object System.Collections.Specialized.OrderedDictionary
|
||||||
$ordered = New-Object System.Collections.Specialized.OrderedDictionary
|
$SortedPairs = $HashtableAst.KeyValuePairs | Sort-Object { $_.Item1.Extent.StartOffset }
|
||||||
|
|
||||||
# Sortiere KeyValuePairs nach ihrer Position im Quelltext
|
foreach($Pair in $SortedPairs){
|
||||||
$sortedKvps = $HashtableAst.KeyValuePairs | Sort-Object { $_.Item1.Extent.StartOffset }
|
$Key = $Pair.Item1.Extent.Text.Trim("'`"")
|
||||||
|
$Ordered.Add($Key, (ConvertFrom-DataAst -Ast $Pair.Item2))
|
||||||
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) {
|
return $Ordered
|
||||||
$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)
|
function ConvertFrom-DataAst {
|
||||||
}
|
Param(
|
||||||
|
[AllowNull()]
|
||||||
return $ordered
|
$Ast
|
||||||
}
|
|
||||||
|
|
||||||
# Datei parsen
|
|
||||||
$errors = $null
|
|
||||||
$tokens = $null
|
|
||||||
$ast = [System.Management.Automation.Language.Parser]::ParseFile(
|
|
||||||
$Path,
|
|
||||||
[ref]$tokens,
|
|
||||||
[ref]$errors
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if ($errors) {
|
if($null -eq $Ast){
|
||||||
throw "Fehler beim Parsen der Datei: $($errors[0].Message)"
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
# Finde die oberste Hashtable
|
if($Ast -is [System.Management.Automation.Language.HashtableAst]){
|
||||||
$hashtableAst = $ast.Find({
|
return ConvertTo-OrderedHashtable -HashtableAst $Ast
|
||||||
$args[0] -is [System.Management.Automation.Language.HashtableAst]
|
|
||||||
}, $true)
|
|
||||||
|
|
||||||
if (-not $hashtableAst) {
|
|
||||||
throw "Keine Hashtable in der Datei gefunden"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ConvertTo-OrderedHashtable -HashtableAst $hashtableAst
|
if($Ast -is [System.Management.Automation.Language.PipelineAst]){
|
||||||
|
return ConvertFrom-DataAst -Ast $Ast.PipelineElements[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if($Ast -is [System.Management.Automation.Language.CommandExpressionAst]){
|
||||||
|
return ConvertFrom-DataAst -Ast $Ast.Expression
|
||||||
|
}
|
||||||
|
|
||||||
|
if($Ast -is [System.Management.Automation.Language.ParenExpressionAst]){
|
||||||
|
return ConvertFrom-DataAst -Ast $Ast.Pipeline
|
||||||
|
}
|
||||||
|
|
||||||
|
if($Ast -is [System.Management.Automation.Language.StatementBlockAst]){
|
||||||
|
$Items = @()
|
||||||
|
foreach($Statement in $Ast.Statements){
|
||||||
|
$Items += ,(ConvertFrom-DataAst -Ast $Statement)
|
||||||
|
}
|
||||||
|
return ,$Items
|
||||||
|
}
|
||||||
|
|
||||||
|
if($Ast -is [System.Management.Automation.Language.ArrayExpressionAst]){
|
||||||
|
return @(ConvertFrom-DataAst -Ast $Ast.SubExpression)
|
||||||
|
}
|
||||||
|
|
||||||
|
if($Ast -is [System.Management.Automation.Language.ArrayLiteralAst]){
|
||||||
|
$Items = @()
|
||||||
|
foreach($Element in $Ast.Elements){
|
||||||
|
$Items += ,(ConvertFrom-DataAst -Ast $Element)
|
||||||
|
}
|
||||||
|
return ,$Items
|
||||||
|
}
|
||||||
|
|
||||||
|
if($Ast -is [System.Management.Automation.Language.StringConstantExpressionAst]){
|
||||||
|
return $Ast.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
if($Ast -is [System.Management.Automation.Language.ExpandableStringExpressionAst]){
|
||||||
|
return $Ast.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
if($Ast -is [System.Management.Automation.Language.ConstantExpressionAst]){
|
||||||
|
return $Ast.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
if($Ast -is [System.Management.Automation.Language.VariableExpressionAst]){
|
||||||
|
switch($Ast.VariablePath.UserPath){
|
||||||
|
"true" { return $true }
|
||||||
|
"false" { return $false }
|
||||||
|
"null" { return $null }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($Ast -is [System.Management.Automation.Language.UnaryExpressionAst]){
|
||||||
|
$ChildValue = ConvertFrom-DataAst -Ast $Ast.Child
|
||||||
|
if($Ast.TokenKind -eq [System.Management.Automation.Language.TokenKind]::Minus){
|
||||||
|
return -1 * $ChildValue
|
||||||
|
}
|
||||||
|
return $ChildValue
|
||||||
|
}
|
||||||
|
|
||||||
|
throw "Nicht unterstützter Ausdruck in PSD1: $($Ast.Extent.Text)"
|
||||||
|
}
|
||||||
|
|
||||||
|
$Tokens = $null
|
||||||
|
$Errors = $null
|
||||||
|
$Ast = [System.Management.Automation.Language.Parser]::ParseFile($Path, [ref]$Tokens, [ref]$Errors)
|
||||||
|
|
||||||
|
if($Errors.Count -gt 0){
|
||||||
|
throw "Fehler beim Parsen der Datei: $($Errors[0].Message)"
|
||||||
|
}
|
||||||
|
|
||||||
|
$HashtableAst = $Ast.Find({ $args[0] -is [System.Management.Automation.Language.HashtableAst] }, $true)
|
||||||
|
if($null -eq $HashtableAst){
|
||||||
|
throw "Keine Hashtable in der Datei gefunden."
|
||||||
|
}
|
||||||
|
|
||||||
|
return ConvertTo-OrderedHashtable -HashtableAst $HashtableAst
|
||||||
}
|
}
|
||||||
@@ -1,19 +1,22 @@
|
|||||||
function Load-Templates {
|
function Load-Templates {
|
||||||
|
|
||||||
$flow.SuspendLayout()
|
$flow.SuspendLayout()
|
||||||
$flow.Controls.Clear()
|
$flow.Controls.Clear()
|
||||||
|
|
||||||
# Lokales Tracking-Objekt
|
|
||||||
$selectionTracker = @{
|
$selectionTracker = @{
|
||||||
LastSelectedListBox = $null
|
LastSelectedListBox = $null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path -Path $($settingsManager.Get("TemplatePath")))) {
|
$templatePath = $settingsManager.Get("TemplatePath")
|
||||||
$statusBar.SetText("Status", "Root-Ordner nicht gefunden: $rootPath")
|
if (-not (Test-Path -Path $templatePath)) {
|
||||||
|
$statusBar.SetText("Status", "Template-Ordner nicht gefunden: $templatePath")
|
||||||
|
$flow.ResumeLayout()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
try {
|
try {
|
||||||
$Categories = Get-ChildItem -Path $($settingsManager.Get("TemplatePath")) -Directory -ErrorAction Stop
|
$categories = @(Get-ChildItem -Path $templatePath -Directory -ErrorAction Stop | Where-Object {
|
||||||
|
@(Get-ChildItem -Path $_.FullName -Filter "*.psd1" -File -ErrorAction SilentlyContinue).Count -gt 0
|
||||||
|
})
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
$statusBar.SetText("Status", "Fehler beim Laden: $($_.Exception.Message)")
|
$statusBar.SetText("Status", "Fehler beim Laden: $($_.Exception.Message)")
|
||||||
@@ -23,70 +26,99 @@ function Load-Templates {
|
|||||||
[System.Windows.Forms.MessageBoxButtons]::OK,
|
[System.Windows.Forms.MessageBoxButtons]::OK,
|
||||||
[System.Windows.Forms.MessageBoxIcon]::Error
|
[System.Windows.Forms.MessageBoxIcon]::Error
|
||||||
)
|
)
|
||||||
|
$flow.ResumeLayout()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ($Categories.Count -eq 0) {
|
|
||||||
|
if ($categories.Count -eq 0) {
|
||||||
$labelNoCategories = (
|
$labelNoCategories = (
|
||||||
[LabelBuilder]::new("Keine Unterordner gefunden.", 24).
|
[LabelBuilder]::new("Keine Templates gefunden.", 24).
|
||||||
SetDock('Top').
|
SetDock('Top').
|
||||||
SetTextAlign([System.Drawing.ContentAlignment]::MiddleLeft).
|
SetTextAlign([System.Drawing.ContentAlignment]::MiddleLeft).
|
||||||
SetPadding(5, 0, 0, 0).
|
SetPadding(5, 0, 0, 0).
|
||||||
Build()
|
Build()
|
||||||
)
|
)
|
||||||
$flow.Controls.Add($labelNoCategories)
|
$flow.Controls.Add($labelNoCategories)
|
||||||
|
$flow.ResumeLayout()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
foreach ($Categorie in $Categories) {
|
|
||||||
|
|
||||||
$GroupBox = (
|
foreach ($category in $categories) {
|
||||||
[GroupBoxBuilder]::new($Categorie.Name).
|
$groupBoxWidth = [Math]::Max(($flow.ClientSize.Width - 20), 220)
|
||||||
#SetAutoSize($true).
|
|
||||||
SetWidth(0).
|
$groupBox = (
|
||||||
|
[GroupBoxBuilder]::new($category.Name).
|
||||||
|
SetWidth($groupBoxWidth).
|
||||||
SetHeight(90).
|
SetHeight(90).
|
||||||
SetMargin(4).
|
SetMargin(4).
|
||||||
SetPadding(10).
|
SetPadding(10).
|
||||||
AddTo($flow)
|
AddTo($flow)
|
||||||
)
|
)
|
||||||
|
|
||||||
$GroupBox.Tag = $Categorie.Name
|
$groupBox.Tag = $category.Name
|
||||||
|
|
||||||
$Files = Get-ChildItem -Path $Categorie.FullName -Filter "*.psd1" -File -ErrorAction SilentlyContinue | Sort-Object Name
|
$files = @(Get-ChildItem -Path $category.FullName -Filter "*.psd1" -File -ErrorAction SilentlyContinue |
|
||||||
if ($Files.Count -eq 0) {
|
Where-Object { $_.BaseName -ne "Default" -and $_.BaseName -notlike "*.Default" } |
|
||||||
$ListBox = (
|
Sort-Object Name)
|
||||||
[ListBoxBuilder]::new().
|
|
||||||
SetDock('Fill'). # Füllt die GroupBox aus
|
|
||||||
AddItem("Keine Templates").
|
|
||||||
AddTo($GroupBox)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
$ListBox = (
|
$listBox = (
|
||||||
[ListBoxBuilder]::new().
|
[ListBoxBuilder]::new().
|
||||||
SetDock('Fill').
|
SetDock('Fill').
|
||||||
AddSelectedIndexChangedHandler({
|
AddSelectedIndexChangedHandler({
|
||||||
param($s, $e)
|
param($s, $e)
|
||||||
|
|
||||||
if ($null -ne $selectionTracker.LastSelectedListBox -and
|
if ($null -ne $selectionTracker.LastSelectedListBox -and $selectionTracker.LastSelectedListBox -ne $s) {
|
||||||
$selectionTracker.LastSelectedListBox -ne $s) {
|
|
||||||
|
|
||||||
# Deselektiere die vorherige ListBox
|
|
||||||
$selectionTracker.LastSelectedListBox.ClearSelected()
|
$selectionTracker.LastSelectedListBox.ClearSelected()
|
||||||
}
|
}
|
||||||
|
|
||||||
# Speichere die aktuelle ListBox
|
|
||||||
$selectionTracker.LastSelectedListBox = $s
|
$selectionTracker.LastSelectedListBox = $s
|
||||||
|
|
||||||
$selectedItem = $s.SelectedItem
|
$selectedItem = $s.SelectedItem
|
||||||
|
|
||||||
if ($null -ne $selectedItem -and ($selectedItem -isnot [string])) {
|
if ($null -ne $selectedItem -and ($selectedItem -isnot [string])) {
|
||||||
$currentGroupBox = $s.Parent
|
$currentGroupBox = $s.Parent
|
||||||
$statusBar.SetText("Status", "Ausgewählt: $($selectedItem.FullName) [Kategorie: $($currentGroupBox.Tag)]")
|
$statusBar.SetText("Status", "Ausgewählt: $($selectedItem.FullName) [Kategorie: $($currentGroupBox.Tag)]")
|
||||||
Show-Template -Template $([TemplateBuilder]::new($selectedItem.FullName).ResolveDeploymentDataVariables())
|
|
||||||
|
try {
|
||||||
|
if (-not (Get-Command -Name Get-TemplatePreviewData -ErrorAction SilentlyContinue)) {
|
||||||
|
$previewFunctionPath = Join-Path -Path $settingsManager.Get("FunctionsPath") -ChildPath "Get-TemplatePreviewData.ps1"
|
||||||
|
if (Test-Path -Path $previewFunctionPath -PathType Leaf) {
|
||||||
|
. $previewFunctionPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Get-Command -Name Get-TemplatePreviewData -ErrorAction SilentlyContinue)) {
|
||||||
|
$templateData = Import-OrderedPowerShellDataFile -Path $selectedItem.FullName -ErrorAction Stop
|
||||||
|
Show-Template -Template $templateData
|
||||||
|
$statusBar.SetText("Status", "Vorschau ohne Default-Merge geladen: Get-TemplatePreviewData ist nicht verfügbar")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$preview = Get-TemplatePreviewData -TemplatePath $selectedItem.FullName -ErrorAction Stop
|
||||||
|
$previewData = if ($null -ne $preview.Display) { $preview.Display } elseif ($null -ne $preview.Resolved) { $preview.Resolved } else { $preview.Merged }
|
||||||
|
|
||||||
|
Show-Template -Template $previewData
|
||||||
|
Update-ParametersPanel -ConfigurationData $preview.Merged
|
||||||
|
|
||||||
|
if ($null -ne $preview.ResolveError) {
|
||||||
|
$statusBar.SetText("Status", "Vorschau gemerged, Resolve unvollständig: $($preview.ResolveError.Exception.Message)")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$statusBar.SetText("Status", "Vorschau geladen: $($preview.Files.Count) Datei(en) inklusive Defaults")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
[System.Windows.Forms.MessageBox]::Show(
|
||||||
|
"Datei konnte nicht geladen werden: $($_.Exception.Message)",
|
||||||
|
"Fehler",
|
||||||
|
[System.Windows.Forms.MessageBoxButtons]::OK,
|
||||||
|
[System.Windows.Forms.MessageBoxIcon]::Error
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.GetNewClosure()).
|
}.GetNewClosure()).
|
||||||
AddMouseDoubleClickHandler({
|
AddMouseDoubleClickHandler({
|
||||||
param($s, $e)
|
param($s, $e)
|
||||||
|
|
||||||
$selectedItem = $s.SelectedItem
|
$selectedItem = $s.SelectedItem
|
||||||
if ($null -ne $selectedItem -and ($selectedItem -isnot [string])) {
|
if ($null -ne $selectedItem -and ($selectedItem -isnot [string])) {
|
||||||
$fullPath = $selectedItem.FullName
|
$fullPath = $selectedItem.FullName
|
||||||
@@ -94,7 +126,12 @@ function Load-Templates {
|
|||||||
[System.Windows.Forms.MessageBox]::Show("Datei nicht gefunden: $fullPath", "Fehler", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
|
[System.Windows.Forms.MessageBox]::Show("Datei nicht gefunden: $fullPath", "Fehler", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
$newItem = New-Object PSObject -Property @{ BaseName = [System.IO.Path]::GetFileNameWithoutExtension($fullPath); FullName = $fullPath }
|
|
||||||
|
$newItem = New-Object PSObject -Property @{
|
||||||
|
BaseName = [System.IO.Path]::GetFileNameWithoutExtension($fullPath)
|
||||||
|
FullName = $fullPath
|
||||||
|
}
|
||||||
|
|
||||||
if (-not ($selectionList.Items | Where-Object { $_.FullName -eq $newItem.FullName })) {
|
if (-not ($selectionList.Items | Where-Object { $_.FullName -eq $newItem.FullName })) {
|
||||||
$selectionList.Items.Add($newItem) | Out-Null
|
$selectionList.Items.Add($newItem) | Out-Null
|
||||||
$stateManager.SetState("hasSelection", $true)
|
$stateManager.SetState("hasSelection", $true)
|
||||||
@@ -106,18 +143,27 @@ function Load-Templates {
|
|||||||
$statusBar.SetText("Status", "Datei bereits in der Auswahl")
|
$statusBar.SetText("Status", "Datei bereits in der Auswahl")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}).
|
||||||
|
AddTo($groupBox)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if($files.Count -eq 0){
|
||||||
|
$listBox.Items.Add("Keine Templates vorhanden") | Out-Null
|
||||||
|
}else{
|
||||||
foreach ($file in $files) {
|
foreach ($file in $files) {
|
||||||
$item = New-Object PSObject -Property @{ BaseName = $file.BaseName; FullName = $file.FullName }
|
$item = New-Object PSObject -Property @{
|
||||||
$ListBox.AddItem($item)
|
BaseName = $file.BaseName
|
||||||
$ListBox.AddTo($GroupBox)
|
FullName = $file.FullName
|
||||||
|
}
|
||||||
|
$listBox.Items.Add($item) | Out-Null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$flow.ResumeLayout()
|
$flow.ResumeLayout()
|
||||||
}
|
|
||||||
|
foreach ($groupBox in $flow.Controls) {
|
||||||
|
$groupBox.Width = [Math]::Max(($flow.ClientSize.Width - 20), 220)
|
||||||
}
|
}
|
||||||
|
|
||||||
$form.Form.Invoke([Action] {
|
$form.Form.Invoke([Action] {
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
function Merge-ConfigurationData {
|
|
||||||
[CmdletBinding()]
|
|
||||||
Param(
|
|
||||||
[Parameter(Mandatory = $true)]
|
|
||||||
[System.Collections.Hashtable]
|
|
||||||
$Template,
|
|
||||||
[Parameter(Mandatory = $true)]
|
|
||||||
[System.Collections.Hashtable]
|
|
||||||
$Deployment,
|
|
||||||
[Parameter(Mandatory = $false)]
|
|
||||||
[System.Collections.Hashtable]
|
|
||||||
$Output
|
|
||||||
)
|
|
||||||
|
|
||||||
# Prüfe auf zirkuläre Referenzen
|
|
||||||
if ($Template -eq $Deployment) {
|
|
||||||
throw "Zirkuläre Referenz erkannt"
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($Output -eq $null) {
|
|
||||||
$Output = $Deployment
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($Property in $Template.GetEnumerator()) {
|
|
||||||
if ($Property.Value -is [System.Collections.Hashtable]) {
|
|
||||||
Write-Verbose "Key [$($Property.Name)] is a Hashtable"
|
|
||||||
if ($null -ne $Deployment.$($Property.Name)) {
|
|
||||||
Write-Verbose "Key [$($Property.Name)] is present in Deployment Data"
|
|
||||||
$Output.($Property.Name) = Merge-ConfigurationData -Template $Template.$($Property.Name) -Deployment $Deployment.$($Property.Name) -Output $Output.$($Property.Name)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Verbose "Key [$($Property.Name)] is not present in Deployment Data"
|
|
||||||
$Output.Add($($Property.Name), $Template.$($Property.Name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elseif ($Property.Value -is [System.Collections.Specialized.OrderedDictionary]) {
|
|
||||||
Write-Verbose "Key [$($Property.Name)] is a Ordered Dictionary"
|
|
||||||
if ($null -ne $Deployment.$($Property.Name)) {
|
|
||||||
Write-Verbose "Key [$($Property.Name)] is present in Deployment Data"
|
|
||||||
$Output.($Property.Name) = Merge-ConfigurationData -Template $Template.$($Property.Name) -Deployment $Deployment.$($Property.Name) -Output $Output.$($Property.Name)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Verbose "Key [$($Property.Name)] is not present in Deployment Data"
|
|
||||||
$Output.Add($($Property.Name), $Template.$($Property.Name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elseif ($Property.Value -is [System.Array]) {
|
|
||||||
Write-Verbose "$($Property.Name) is ein Array"
|
|
||||||
Write-Verbose "Total Items in Template Array [$($Property.Value.Count)]"
|
|
||||||
Write-Verbose "Total Items in Deployment Array [$($Deployment.$($Property.Name).Count)]"
|
|
||||||
if ($null -ne $Deployment.$($Property.Name)) {
|
|
||||||
Write-Verbose "Array is defined in Deployment"
|
|
||||||
for ($i = 0; $i -lt $Property.Value.Count; $i++) {
|
|
||||||
|
|
||||||
$SearchItem = $($Property.Value[$i].GetEnumerator() | Where-Object { ($_.Value -is [String]) -and ($_.Name -like "*Name") })[0]
|
|
||||||
if ($($Deployment.$($Property.Name) | ? { $_.($SearchItem.Name) -eq $SearchItem.Value })) {
|
|
||||||
Merge-ConfigurationData -Template $Property.Value[$i] -Deployment $($Deployment.$($Property.Name) | ? { $_.($SearchItem.Name) -eq $SearchItem.Value }) -Output $($Output.$($Property.Name) | ? { $_.($SearchItem.Name) -eq $SearchItem.Value }) | Out-Null
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Verbose "Pair $($Key.Name) - $($Key.Value) not present"
|
|
||||||
$Output.$($Property.Name) += $Property.Value[$i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Verbose "Array is not defined in Deployment"
|
|
||||||
$Output.$($Property.Name) = $Template.$($Property.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Verbose "$($Property.Name) is a String or Integer Value"
|
|
||||||
if ($null -eq $Deployment.$($Property.Name)) {
|
|
||||||
|
|
||||||
$Output.Add($Property.Name, $Template.($Property.Name))
|
|
||||||
|
|
||||||
}
|
|
||||||
elseif ($Deployment.$($Property.Name) -ne $Property.Value) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $Output
|
|
||||||
}
|
|
||||||
@@ -1,35 +1,74 @@
|
|||||||
function Merge-Templates {
|
function Merge-Templates {
|
||||||
$Errors = @()
|
$Errors = @()
|
||||||
[System.Collections.Hashtable] $ConfigurationData = @{}
|
$MergedConfigurationData = $null
|
||||||
#[System.Collections.Specialized.OrderedDictionary] $ConfigurationData = @{}
|
$MergeFiles = @()
|
||||||
|
$AddedDefaultFiles = @{}
|
||||||
|
|
||||||
for ($i = 0; $i -lt $selectionList.Items.Count; $i++) {
|
for ($i = 0; $i -lt $selectionList.Items.Count; $i++) {
|
||||||
$item = $selectionList.Items[$i]
|
$item = $selectionList.Items[$i]
|
||||||
$file = $item.FullName
|
$file = $item.FullName
|
||||||
if (-not (Test-Path $file)) { $Errors += "Datei nicht gefunden: $file"; continue }
|
|
||||||
|
|
||||||
|
if (-not (Test-Path $file)) {
|
||||||
|
$Errors += "Datei nicht gefunden: $file"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$directory = Split-Path -Path $file -Parent
|
||||||
|
$defaultFiles = @(Get-ChildItem -Path $directory -Filter "*.psd1" -File -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object { $_.BaseName -eq "Default" -or $_.BaseName -like "*.Default" } |
|
||||||
|
Sort-Object Name)
|
||||||
|
|
||||||
|
foreach($defaultFile in $defaultFiles){
|
||||||
|
if(-not $AddedDefaultFiles.ContainsKey($defaultFile.FullName)){
|
||||||
|
$MergeFiles += $defaultFile.FullName
|
||||||
|
$AddedDefaultFiles[$defaultFile.FullName] = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$MergeFiles += $file
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($file in $MergeFiles){
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
$TemplateData = Import-OrderedPowerShellDataFile -Path $file -ErrorAction Stop
|
$TemplateData = Import-PowerShellDataFile -Path $file -ErrorAction Stop
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
$Errors += "Datei konnte nicht importiert werden"
|
$Errors += "Datei konnte nicht importiert werden: $file"
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
$ConfigurationData = Merge-ConfigurationData -Template $ConfigurationData -Deployment $TemplateData
|
if($null -eq $MergedConfigurationData){
|
||||||
|
$MergedConfigurationData = $TemplateData
|
||||||
|
}else{
|
||||||
|
$MergedConfigurationData = Merge-DSCConfigurationData -Template $MergedConfigurationData -Deployment $TemplateData
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
$Errors += "Fehler beim Verarbeiten $($file): $($_.Exception.Message)"
|
$Errors += "Fehler beim Verarbeiten $($file): $($_.Exception.Message)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($null -ne $ConfigurationData) {
|
if ($null -ne $MergedConfigurationData) {
|
||||||
Update-TreeView -ConfigurationData $([TemplateBuilder]::new($ConfigurationData).ResolveDeploymentDataVariables())
|
try {
|
||||||
$statusBar.SetText("Status", "Merge erfolgreich: $($selectionList.Items.Count) Dateien")
|
$script:MergedConfigurationData = $MergedConfigurationData
|
||||||
|
$script:ResolvedConfigurationData = Resolve-DSCConfigurationData -ConfigurationData $MergedConfigurationData
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$Errors += "Fehler beim Auflösen der ConfigurationData: $($_.Exception.Message)"
|
||||||
|
$script:ResolvedConfigurationData = $null
|
||||||
|
}
|
||||||
|
|
||||||
|
if($null -ne $script:ResolvedConfigurationData){
|
||||||
|
Update-TreeView -ConfigurationData $script:ResolvedConfigurationData
|
||||||
|
}else{
|
||||||
|
Update-TreeView -ConfigurationData $MergedConfigurationData
|
||||||
|
}
|
||||||
|
|
||||||
|
$statusBar.SetText("Status", "Merge erfolgreich: $($selectionList.Items.Count) Queue-Dateien, $($MergeFiles.Count) inklusive Defaults")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
Update-TreeView -ConfigurationData $MergedConfigurationData
|
||||||
Update-TreeView -ConfigurationData $ConfigurationData
|
|
||||||
$statusLabel.Text = "Merge ergab kein Ergebnis"
|
$statusLabel.Text = "Merge ergab kein Ergebnis"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +76,6 @@ function Merge-Templates {
|
|||||||
[System.Windows.Forms.MessageBox]::Show(($Errors -join "`r`n"), "Merge Warnungen", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Warning)
|
[System.Windows.Forms.MessageBox]::Show(($Errors -join "`r`n"), "Merge Warnungen", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Warning)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return $ConfigurationData
|
return $script:ResolvedConfigurationData
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
function Show-Template {
|
function Show-Template {
|
||||||
Param(
|
Param(
|
||||||
[System.Collections.Hashtable] $Template
|
$Template
|
||||||
)
|
)
|
||||||
$treeView.Nodes.Clear()
|
$treeView.Nodes.Clear()
|
||||||
|
|
||||||
$tempBuilder = [TreeViewBuilder]::new()
|
$tempBuilder = [TreeViewBuilder]::new()
|
||||||
$tempBuilder.control = $treeView
|
$tempBuilder.control = $treeView
|
||||||
$tempBuilder.LoadTemplate($Template, "Template")
|
|
||||||
|
if($null -ne $Template -and $Template.Contains("Resources")){
|
||||||
|
$tempBuilder.LoadTemplate($Template["Resources"], "Template")
|
||||||
|
}else{
|
||||||
|
$treeView.Nodes.Add("No resources found") | Out-Null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,53 +3,63 @@ function Update-ParametersPanel {
|
|||||||
[System.Collections.Hashtable] $ConfigurationData
|
[System.Collections.Hashtable] $ConfigurationData
|
||||||
)
|
)
|
||||||
|
|
||||||
if ($ConfigurationData.Contains("Parameters") -or $ConfigurationData.Contains("Variables")) {
|
foreach ($tabName in @("Parameters", "Variables")) {
|
||||||
|
$existingTabs = @($tabControl.Controls | Where-Object { $_.Text -eq $tabName })
|
||||||
|
foreach ($tab in $existingTabs) {
|
||||||
|
$tabControl.Controls.Remove($tab)
|
||||||
|
$tab.Dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -eq $ConfigurationData) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if ($ConfigurationData.Contains("Parameters")) {
|
if ($ConfigurationData.Contains("Parameters")) {
|
||||||
if (!($tabControl.Controls | ? { $_.Text -eq "Parameters" })) {
|
$parametersTabPage = (
|
||||||
$ParametersTabPage = (
|
|
||||||
[TabPageBuilder]::new("Parameters").
|
[TabPageBuilder]::new("Parameters").
|
||||||
Build()
|
Build()
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
$GridView = (
|
$gridView = (
|
||||||
[DataGridViewBuilder]::new().
|
[DataGridViewBuilder]::new().
|
||||||
SetHeaderColumns(@("Name", "Value")).
|
SetHeaderColumns(@("Name", "Value", "Type", "Required")).
|
||||||
SetHeaderColumnReadOnly("Name").
|
SetHeaderColumnReadOnly("Name").
|
||||||
Build()
|
Build()
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach ($Parameter in $ConfigurationData.Parameters.GetEnumerator()) {
|
foreach ($parameter in $ConfigurationData.Parameters.GetEnumerator()) {
|
||||||
$GridView.Rows.Add($Parameter.Name, $($Parameter.Value.Value)) | Out-Null
|
$value = $parameter.Value
|
||||||
|
$gridView.Rows.Add(
|
||||||
|
$parameter.Name,
|
||||||
|
$value.Value,
|
||||||
|
$value.Type,
|
||||||
|
$value.Required
|
||||||
|
) | Out-Null
|
||||||
}
|
}
|
||||||
$ParametersTabPage.Controls.Add($GridView)
|
|
||||||
$tabControl.Controls.Add($ParametersTabPage)
|
|
||||||
|
|
||||||
|
$parametersTabPage.Controls.Add($gridView)
|
||||||
|
$tabControl.Controls.Add($parametersTabPage)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($ConfigurationData.Contains("Variables")) {
|
if ($ConfigurationData.Contains("Variables")) {
|
||||||
if (!($tabControl.Controls | ? { $_.Text -eq "Variables" })) {
|
$variablesTabPage = (
|
||||||
$VariablesTabPage = (
|
|
||||||
[TabPageBuilder]::new("Variables").
|
[TabPageBuilder]::new("Variables").
|
||||||
Build()
|
Build()
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
$GridView = (
|
$gridView = (
|
||||||
[DataGridViewBuilder]::new().
|
[DataGridViewBuilder]::new().
|
||||||
SetHeaderColumns(@("Name", "Value")).
|
SetHeaderColumns(@("Name", "Value")).
|
||||||
SetHeaderColumnReadOnly("Name").
|
SetHeaderColumnReadOnly("Name").
|
||||||
Build()
|
Build()
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach ($Variable in $ConfigurationData.Variables.GetEnumerator()) {
|
foreach ($variable in $ConfigurationData.Variables.GetEnumerator()) {
|
||||||
$GridView.Rows.Add($Variable.Name, $($Variable.Value)) | Out-Null
|
$gridView.Rows.Add($variable.Name, $variable.Value) | Out-Null
|
||||||
|
|
||||||
}
|
}
|
||||||
$VariablesTabPage.Controls.Add($GridView)
|
|
||||||
$tabControl.Controls.Add($VariablesTabPage)
|
|
||||||
|
|
||||||
}
|
$variablesTabPage.Controls.Add($gridView)
|
||||||
|
$tabControl.Controls.Add($variablesTabPage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,13 +5,23 @@ function Update-TreeView {
|
|||||||
if ($null -ne $ConfigurationData) {
|
if ($null -ne $ConfigurationData) {
|
||||||
$tempBuilder = [TreeViewBuilder]::new()
|
$tempBuilder = [TreeViewBuilder]::new()
|
||||||
$tempBuilder.control = $treeView
|
$tempBuilder.control = $treeView
|
||||||
|
if($ConfigurationData.ContainsKey("Resources")){
|
||||||
$tempBuilder.LoadTemplate($ConfigurationData['Resources'], "Deployment")
|
$tempBuilder.LoadTemplate($ConfigurationData['Resources'], "Deployment")
|
||||||
|
}else{
|
||||||
|
$treeView.Nodes.Clear()
|
||||||
|
$treeView.Nodes.Add("No resources found") | Out-Null
|
||||||
|
}
|
||||||
$statusBar.SetText("Status", "Merged: Anzeige aktualisiert")
|
$statusBar.SetText("Status", "Merged: Anzeige aktualisiert")
|
||||||
$stateManager.SetState("isMerged", $true)
|
$stateManager.SetState("isMerged", $true)
|
||||||
|
$stateManager.SetState("isResolved", $null -ne $script:ResolvedConfigurationData)
|
||||||
$stateManager.UpdateAllButtons()
|
$stateManager.UpdateAllButtons()
|
||||||
|
|
||||||
# Parameter und Variablen Panel aktualisieren
|
# Parameter und Variablen Panel aktualisieren
|
||||||
|
if($null -ne $script:MergedConfigurationData){
|
||||||
|
Update-ParametersPanel -ConfigurationData $script:MergedConfigurationData
|
||||||
|
}else{
|
||||||
Update-ParametersPanel -ConfigurationData $ConfigurationData
|
Update-ParametersPanel -ConfigurationData $ConfigurationData
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
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
|
||||||
13
Templates/Environment/BGW-LAN.psd1
Normal file
13
Templates/Environment/BGW-LAN.psd1
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
@{
|
||||||
|
Parameters = @{
|
||||||
|
DomainLabel = @{
|
||||||
|
Value = 'LAN'
|
||||||
|
}
|
||||||
|
DomainFQDN = @{
|
||||||
|
Value = 'bgw-online.de'
|
||||||
|
}
|
||||||
|
DomainNetBIOS = @{
|
||||||
|
Value = 'BGW-Online'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
@{
|
|
||||||
Resources = @{
|
|
||||||
NonNodeData = @{
|
|
||||||
Services = @{
|
|
||||||
ActiveDirectory = @{
|
|
||||||
Domain = @{
|
|
||||||
FQDN = "contoso.local"
|
|
||||||
NetBIOS = "Contoso"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
244
Templates/Environment/Environment.Default.psd1
Normal file
244
Templates/Environment/Environment.Default.psd1
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
@{
|
||||||
|
Parameters = @{
|
||||||
|
DomainLabel = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = ''
|
||||||
|
Required = $false
|
||||||
|
MinLength = 2
|
||||||
|
MaxLength = 32
|
||||||
|
Pattern = '^[A-Za-z][A-Za-z0-9_-]*$'
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Kurzer logischer Bezeichner der Umgebung oder Domaene.'
|
||||||
|
'en-US' = 'Short logical identifier for the environment or domain.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DomainFQDN = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = ''
|
||||||
|
Required = $true
|
||||||
|
Pattern = '^[A-Za-z0-9.-]+$'
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Vollqualifizierter DNS-Name der Active-Directory-Domaene.'
|
||||||
|
'en-US' = 'Fully qualified DNS name of the Active Directory domain.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DomainNetBIOS = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = ''
|
||||||
|
Required = $true
|
||||||
|
MinLength = 1
|
||||||
|
MaxLength = 15
|
||||||
|
Pattern = '^[A-Za-z0-9_-]+$'
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'NetBIOS-Name der Active-Directory-Domaene.'
|
||||||
|
'en-US' = 'NetBIOS name of the Active Directory domain.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ForestMode = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = 'WinThreshold'
|
||||||
|
AllowedValues = @(
|
||||||
|
'Win2012R2',
|
||||||
|
'WinThreshold'
|
||||||
|
)
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Funktionsebene des Active-Directory-Forests.'
|
||||||
|
'en-US' = 'Functional level of the Active Directory forest.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DomainMode = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = 'WinThreshold'
|
||||||
|
AllowedValues = @(
|
||||||
|
'Win2012R2',
|
||||||
|
'WinThreshold'
|
||||||
|
)
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Funktionsebene der Active-Directory-Domaene.'
|
||||||
|
'en-US' = 'Functional level of the Active Directory domain.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultSiteName = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = 'Default-First-Site-Name'
|
||||||
|
Required = $true
|
||||||
|
MinLength = 1
|
||||||
|
MaxLength = 64
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Standard-AD-Sitename fuer Domaenencontroller und Subnetze.'
|
||||||
|
'en-US' = 'Default AD site name for domain controllers and subnets.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultSubnet = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = ''
|
||||||
|
Required = $false
|
||||||
|
Pattern = '^$|^\d{1,3}(\.\d{1,3}){3}/\d{1,2}$'
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Optionales Standard-Subnetz im CIDR-Format.'
|
||||||
|
'en-US' = 'Optional default subnet in CIDR notation.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DomainAdministratorCredentialName = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = 'DomainAdministrator'
|
||||||
|
Required = $true
|
||||||
|
Sensitive = $true
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Name der Credential-Referenz fuer den Domaenenadministrator.'
|
||||||
|
'en-US' = 'Name of the credential reference for the domain administrator.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SafeModeAdministratorPasswordSecretName = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = 'SafeModeAdministratorPassword'
|
||||||
|
Required = $true
|
||||||
|
Sensitive = $true
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Name der Secret-Referenz fuer das Safe-Mode-Administrator-Kennwort.'
|
||||||
|
'en-US' = 'Name of the secret reference for the safe mode administrator password.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Resources = @{
|
||||||
|
NonNodeData = @{
|
||||||
|
RequiredModules = @(
|
||||||
|
@{
|
||||||
|
Name = 'ActiveDirectoryDsc'
|
||||||
|
Version = '6.7.1'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Services = @{
|
||||||
|
ActiveDirectory = @{
|
||||||
|
Domain = @{
|
||||||
|
Ensure = 'Present'
|
||||||
|
|
||||||
|
FQDN = "[parameters('DomainFQDN')]"
|
||||||
|
NetBIOS = "[parameters('DomainNetBIOS')]"
|
||||||
|
|
||||||
|
ForestMode = "[parameters('ForestMode')]"
|
||||||
|
DomainMode = "[parameters('DomainMode')]"
|
||||||
|
|
||||||
|
DnsDelegation = $false
|
||||||
|
|
||||||
|
Credentials = @{
|
||||||
|
DomainAdministrator = @{
|
||||||
|
CredentialName = "[parameters('DomainAdministratorCredentialName')]"
|
||||||
|
}
|
||||||
|
|
||||||
|
SafeModeAdministrator = @{
|
||||||
|
SecretName = "[parameters('SafeModeAdministratorPasswordSecretName')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DomainControllers = @(
|
||||||
|
@{
|
||||||
|
NodeName = '*'
|
||||||
|
Ensure = 'Present'
|
||||||
|
InstallDns = $true
|
||||||
|
IsGlobalCatalog = $true
|
||||||
|
SiteName = "[parameters('DefaultSiteName')]"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Sites = @(
|
||||||
|
@{
|
||||||
|
Name = "[parameters('DefaultSiteName')]"
|
||||||
|
Ensure = 'Present'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Subnets = @(
|
||||||
|
@{
|
||||||
|
Name = "[parameters('DefaultSubnet')]"
|
||||||
|
SiteName = "[parameters('DefaultSiteName')]"
|
||||||
|
Ensure = 'Present'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
OrganizationalUnits = @(
|
||||||
|
@{
|
||||||
|
Name = 'Servers'
|
||||||
|
Path = "[concat('DC=', replace(parameters('DomainFQDN'), '.', ',DC='))]"
|
||||||
|
Ensure = 'Present'
|
||||||
|
ProtectedFromAccidentalDeletion = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
@{
|
||||||
|
Name = 'Service Accounts'
|
||||||
|
Path = "[concat('DC=', replace(parameters('DomainFQDN'), '.', ',DC='))]"
|
||||||
|
Ensure = 'Present'
|
||||||
|
ProtectedFromAccidentalDeletion = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
@{
|
||||||
|
Name = 'Groups'
|
||||||
|
Path = "[concat('DC=', replace(parameters('DomainFQDN'), '.', ',DC='))]"
|
||||||
|
Ensure = 'Present'
|
||||||
|
ProtectedFromAccidentalDeletion = $true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Groups = @(
|
||||||
|
@{
|
||||||
|
GroupName = 'GG-SharePoint-Admins'
|
||||||
|
Path = "[concat('OU=Groups,DC=', replace(parameters('DomainFQDN'), '.', ',DC='))]"
|
||||||
|
Scope = 'Global'
|
||||||
|
Category = 'Security'
|
||||||
|
Ensure = 'Present'
|
||||||
|
Members = @()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Users = @(
|
||||||
|
@{
|
||||||
|
UserName = 'SVC_SHP_Setup'
|
||||||
|
Path = "[concat('OU=Service Accounts,DC=', replace(parameters('DomainFQDN'), '.', ',DC='))]"
|
||||||
|
Ensure = 'Present'
|
||||||
|
Enabled = $true
|
||||||
|
Password = @{
|
||||||
|
SecretName = 'SVC_SHP_Setup'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Trusts = @()
|
||||||
|
|
||||||
|
Dns = @{
|
||||||
|
Forwarders = @()
|
||||||
|
ReverseLookupZones = @()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
200
Templates/Service/SharePointServer.Default.psd1
Normal file
200
Templates/Service/SharePointServer.Default.psd1
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
@{
|
||||||
|
Parameters = @{
|
||||||
|
DatabasePrefix = @{
|
||||||
|
Type = 'string'
|
||||||
|
Value = 'SharePoint'
|
||||||
|
DefaultValue = 'SharePoint'
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Praefix fuer alle von der SharePoint-Farm angelegten Datenbanken.'
|
||||||
|
'en-US' = 'Prefix for all databases created by the SharePoint farm.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ServiceDatabaseSegment = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = 'Services'
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Namenssegment fuer SharePoint-Service-Datenbanken innerhalb des Datenbanknamens.'
|
||||||
|
'en-US' = 'Name segment used for SharePoint service databases within the database name.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ContentDatabaseSegment = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = 'Content'
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Namenssegment fuer SharePoint-Content-Datenbanken innerhalb des Datenbanknamens.'
|
||||||
|
'en-US' = 'Name segment used for SharePoint content databases within the database name.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ServiceApplicationPoolDefault = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = 'SharePoint Service Applications'
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Anzeigename des Standard-Application-Pools fuer SharePoint-Serviceanwendungen.'
|
||||||
|
'en-US' = 'Display name of the default application pool for SharePoint service applications.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ServiceApplicationPoolUserProfileService = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = 'SharePoint User Profile Services'
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Anzeigename des Application-Pools fuer den SharePoint User Profile Service.'
|
||||||
|
'en-US' = 'Display name of the application pool for the SharePoint User Profile Service.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ServiceApplicationPoolDefaultAccount = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = 'SVC_SHP_SAP'
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Kontoname fuer den Standard-Application-Pool der SharePoint-Serviceanwendungen.'
|
||||||
|
'en-US' = 'Account name used by the default application pool for SharePoint service applications.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WebApplicationPoolDefault = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = 'SharePoint Web Applications'
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Anzeigename des Standard-Application-Pools fuer SharePoint-Webanwendungen.'
|
||||||
|
'en-US' = 'Display name of the default application pool for SharePoint web applications.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WebApplicationPoolDefaultAccount = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = 'SVC_SHP_WAP'
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Kontoname fuer den Standard-Application-Pool der SharePoint-Webanwendungen.'
|
||||||
|
'en-US' = 'Account name used by the default application pool for SharePoint web applications.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DatabaseInstanceName = @{
|
||||||
|
Type = 'string'
|
||||||
|
DefaultValue = 'SQL_Server'
|
||||||
|
Metadata = @{
|
||||||
|
Description = @{
|
||||||
|
'de-DE' = 'Standard-SQL-Instanzname fuer SharePoint-Datenbankverbindungen und Aliase.'
|
||||||
|
'en-US' = 'Default SQL instance name used for SharePoint database connections and aliases.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Variables = @{
|
||||||
|
ServiceDbPrefix = "[concat(parameters('DatabasePrefix'),'_',parameters('ServiceDatabaseSegment'),'_')]"
|
||||||
|
ContentDbPrefix = "[concat(parameters('DatabasePrefix'),'_',parameters('ContentDatabaseSegment'),'_')]"
|
||||||
|
ConfigDbName = "[concat(parameters('DatabasePrefix'),'_','Farm_Config')]"
|
||||||
|
AdminDbName = "[concat(parameters('DatabasePrefix'),'_','Farm_AdminContent')]"
|
||||||
|
}
|
||||||
|
Resources = @{
|
||||||
|
NonNodeData = @{
|
||||||
|
Services = @{
|
||||||
|
SharePoint = @{
|
||||||
|
General = @{
|
||||||
|
ProductKey = '0000-0000-0000-0000-0000'
|
||||||
|
}
|
||||||
|
Windows = @{
|
||||||
|
Registry = @{
|
||||||
|
DisableLoopbackCheck = @{
|
||||||
|
Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa'
|
||||||
|
Name = 'DisableLoopbackCheck'
|
||||||
|
Type = 'DWord'
|
||||||
|
Value = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Database = @{
|
||||||
|
SQLAlias = @{
|
||||||
|
SQLServer = @{
|
||||||
|
ServerName = ''
|
||||||
|
InstanceName = "[parameters('DatabaseInstanceName')]"
|
||||||
|
TcpPort = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Farm = @{
|
||||||
|
Passphrase = 'Use-SecureString-Or-KeyVault'
|
||||||
|
ConfigDatabaseName = "[variables('ConfigDbName')]"
|
||||||
|
AdminContentDatabase = "[variables('AdminDbName')]"
|
||||||
|
CentralAdminPort = 2016
|
||||||
|
CentralAdminAuth = 'NTLM' # oder Kerberos
|
||||||
|
ServiceApplicationPools = @{
|
||||||
|
Default = @{
|
||||||
|
Name = "[parameters('ServiceApplicationPoolDefault')]"
|
||||||
|
Account = 'CONTOSO\sp_services'
|
||||||
|
}
|
||||||
|
|
||||||
|
UserProfile = @{
|
||||||
|
Name = "[parameters('ServiceApplicationPoolUserProfileService')]"
|
||||||
|
Account = 'CONTOSO\sp_ups'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ServiceApplications = @{
|
||||||
|
ManagedMetadataService = @{
|
||||||
|
Provision = $true
|
||||||
|
Name = 'Managed Metadata Service'
|
||||||
|
ApplicationPool = 'SharePoint Service Applications'
|
||||||
|
DatabaseName = "[concat(variables('ServiceDbPrefix'), 'ManagedMetadata')]"
|
||||||
|
}
|
||||||
|
|
||||||
|
UserProfileService = @{
|
||||||
|
Provision = $true
|
||||||
|
Name = 'User Profile Service'
|
||||||
|
ApplicationPool = 'SharePoint User Profile Services'
|
||||||
|
ProfileDBName = "[concat(variables('ServiceDbPrefix'), 'UserProfile_ProfileDB')]"
|
||||||
|
SocialDBName = "[concat(variables('ServiceDbPrefix'), 'UserProfile_SocialDB')]"
|
||||||
|
SyncDBName = "[concat(variables('ServiceDbPrefix'), 'UserProfile_SyncDB')]"
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchService = @{
|
||||||
|
Provision = $true
|
||||||
|
Name = 'Search Service Application'
|
||||||
|
ApplicationPool = 'SharePoint Service Applications'
|
||||||
|
DatabaseName = "[concat(variables('ServiceDbPrefix'),'Search')]"
|
||||||
|
}
|
||||||
|
|
||||||
|
StateService = @{
|
||||||
|
Provision = $true
|
||||||
|
DatabaseName = "[concat(variables('ServiceDbPrefix'),'StateService')]"
|
||||||
|
}
|
||||||
|
|
||||||
|
UsageAndHealthService = @{
|
||||||
|
Provision = $true
|
||||||
|
DatabaseName = "[concat(variables('ServiceDbPrefix'),'UsageAndHealth')]"
|
||||||
|
}
|
||||||
|
|
||||||
|
AppManagementService = @{
|
||||||
|
Provision = $true
|
||||||
|
DatabaseName = "[concat(variables('ServiceDbPrefix'),'AppManagement')]"
|
||||||
|
}
|
||||||
|
|
||||||
|
SubscriptionSettingsService = @{
|
||||||
|
Provision = $true
|
||||||
|
DatabaseName = "[concat(variables('ServiceDbPrefix'),'SubscriptionSettings')]"
|
||||||
|
}
|
||||||
|
|
||||||
|
SecureStoreService = @{
|
||||||
|
Provision = $true
|
||||||
|
Name = 'Secure Store Service'
|
||||||
|
ApplicationPool = 'SharePoint Service Applications'
|
||||||
|
DatabaseName = "[concat(variables('ServiceDbPrefix'),'SecureStore')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
@{
|
|
||||||
Parameters = @{
|
|
||||||
DatabasePrefix = @{
|
|
||||||
Type = 'string'
|
|
||||||
Value = 'SharePoint'
|
|
||||||
DefaultValue = 'SP'
|
|
||||||
Metadata = @{
|
|
||||||
Description = 'Prefix für alle Datenbanknamen'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ServiceDatabasePrefix = @{
|
|
||||||
Type = 'string'
|
|
||||||
DefaultValue = 'Services'
|
|
||||||
}
|
|
||||||
ContentDatabasePrefix = @{
|
|
||||||
Type = 'string'
|
|
||||||
DefaultValue = 'Content'
|
|
||||||
}
|
|
||||||
ServiceApplicationPoolDefault = @{
|
|
||||||
Type = 'string'
|
|
||||||
DefaultValue = 'SharePoint Service Applications'
|
|
||||||
}
|
|
||||||
ServiceApplicationPoolUserProfileService = @{
|
|
||||||
Type = 'string'
|
|
||||||
DefaultValue = 'SharePoint User Profile Services'
|
|
||||||
}
|
|
||||||
DatbaseInstanceName = @{
|
|
||||||
Type = 'string'
|
|
||||||
DefaultValue = 'mssqlserver'
|
|
||||||
Metadata = @{
|
|
||||||
Description = 'Instanz Name für die Standart Instanz'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Variables = @{
|
|
||||||
ServiceDbPrefix = "[Concat(Parameter('DatabasePrefix'),'_',Parameter('ServiceDatabasePrefix'),'_')]"
|
|
||||||
ContentDbPrefix = "[Concat(Parameter('DatabasePrefix'),'_',Parameter('ServiceDatabasePrefix'),'_')]"
|
|
||||||
ConfigDbName = "[Concat(Parameter('DatabasePrefix'),'_','Farm_Config')]"
|
|
||||||
AdminDbName = "[Concat(Parameter('DatabasePrefix'),'_','Farm_AdminContent')]"
|
|
||||||
HZDTest = "[Substring(Parameter('DatbaseInstanceName'),0,5)]"
|
|
||||||
Test = "[ToUpper(Parameter('DatbaseInstanceName'),0,5)]"
|
|
||||||
}
|
|
||||||
Resources = @{
|
|
||||||
NonNodeData = @{
|
|
||||||
Services = @{
|
|
||||||
SharePoint = @{
|
|
||||||
General = @{
|
|
||||||
ProductKey = '0000-0000-0000-0000-0000'
|
|
||||||
}
|
|
||||||
Windows = @{
|
|
||||||
Registry = @{
|
|
||||||
DisableLoopbackCheck = @{
|
|
||||||
Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa'
|
|
||||||
Name = 'DisableLoopbackCheck'
|
|
||||||
Type = 'DWord'
|
|
||||||
Value = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Database = @{
|
|
||||||
SQLAlias = @{
|
|
||||||
SQLServer = @{
|
|
||||||
ServerName = ''
|
|
||||||
InstanceName = ''
|
|
||||||
TcpPort = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Farm = @{
|
|
||||||
Passphrase = 'Use-SecureString-Or-KeyVault'
|
|
||||||
ConfigDatabaseName = "[Variable('ConfigDbName')]"
|
|
||||||
AdminContentDatabase = "[Variable('AdminDbName')]"
|
|
||||||
CentralAdminPort = 2016
|
|
||||||
CentralAdminAuth = 'NTLM' # oder Kerberos
|
|
||||||
ServiceApplicationPools = @{
|
|
||||||
Default = @{
|
|
||||||
Name = "[Parameter('ServiceApplicationPoolDefault')]"
|
|
||||||
Account = 'CONTOSO\sp_services'
|
|
||||||
}
|
|
||||||
|
|
||||||
UserProfile = @{
|
|
||||||
Name = "[Parameter('ServiceApplicationPoolUserProfileService')]"
|
|
||||||
Account = 'CONTOSO\sp_ups'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ServiceApplications = @{
|
|
||||||
ManagedMetadataService = @{
|
|
||||||
Provision = $true
|
|
||||||
Name = 'Managed Metadata Service'
|
|
||||||
ApplicationPool = 'SharePoint Service Applications'
|
|
||||||
DatabaseName = "[Concat(Variable('ServiceDbPrefix'), 'ManagedMetadata')]"
|
|
||||||
}
|
|
||||||
|
|
||||||
UserProfileService = @{
|
|
||||||
Provision = $true
|
|
||||||
Name = 'User Profile Service'
|
|
||||||
ApplicationPool = 'SharePoint User Profile Services'
|
|
||||||
ProfileDBName = "[Concat(Variable('ServiceDbPrefix'), 'UserProfile_ProfileDB')]"
|
|
||||||
SocialDBName = "[Concat(Variable('ServiceDbPrefix'), 'UserProfile_SocialDB')]"
|
|
||||||
SyncDBName = "[Concat(Variable('ServiceDbPrefix'), 'UserProfile_SyncDB')]"
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchService = @{
|
|
||||||
Provision = $true
|
|
||||||
Name = 'Search Service Application'
|
|
||||||
ApplicationPool = 'SharePoint Service Applications'
|
|
||||||
DatabaseName = "[Concat(Variable('ServiceDbPrefix'),'Search')]"
|
|
||||||
}
|
|
||||||
|
|
||||||
StateService = @{
|
|
||||||
Provision = $true
|
|
||||||
DatabaseName = "[Concat(Variable('ServiceDbPrefix'),'StateService')]"
|
|
||||||
}
|
|
||||||
|
|
||||||
UsageAndHealthService = @{
|
|
||||||
Provision = $true
|
|
||||||
DatabaseName = "[Concat(Variable('ServiceDbPrefix'),'UsageAndHealth')]"
|
|
||||||
}
|
|
||||||
|
|
||||||
AppManagementService = @{
|
|
||||||
Provision = $true
|
|
||||||
DatabaseName = "[Concat(Variable('ServiceDbPrefix'),'AppManagement')]"
|
|
||||||
}
|
|
||||||
|
|
||||||
SubscriptionSettingsService = @{
|
|
||||||
Provision = $true
|
|
||||||
DatabaseName = "[Concat(Variable('ServiceDbPrefix'),'SubscriptionSettings')]"
|
|
||||||
}
|
|
||||||
|
|
||||||
SecureStoreService = @{
|
|
||||||
Provision = $true
|
|
||||||
Name = 'Secure Store Service'
|
|
||||||
ApplicationPool = 'SharePoint Service Applications'
|
|
||||||
DatabaseName = "[Concat(Variable('ServiceDbPrefix'),'SecureStore')]"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user