Version 1.0.0 Release #1

Merged
Torsten merged 7 commits from dev into main 2026-04-21 13:52:34 +00:00
4 changed files with 271 additions and 281 deletions
Showing only changes of commit 7c9b854aec - Show all commits

3
.gitignore vendored
View File

@@ -1,2 +1,3 @@
.git .git
.sample .sample
.output

View File

@@ -24,7 +24,7 @@
$Output.($Property.Name) = Merge-ConfigurationData -Template $Template.$($Property.Name) -Deployment $Deployment.$($Property.Name) -Output $Output.$($Property.Name) $Output.($Property.Name) = Merge-ConfigurationData -Template $Template.$($Property.Name) -Deployment $Deployment.$($Property.Name) -Output $Output.$($Property.Name)
}else{ }else{
Write-Verbose "Key [$($Property.Name)] is not present in Deployment Data" Write-Verbose "Key [$($Property.Name)] is not present in Deployment Data"
$Output.Add($($Property.Name),$Template.$($Property.Name)) $Output.Add($($Property.Name),(Copy-ConfigurationDataValue -Value $Template.$($Property.Name)))
} }
}elseif($Property.Value -is [System.Collections.Specialized.OrderedDictionary]){ }elseif($Property.Value -is [System.Collections.Specialized.OrderedDictionary]){
Write-Verbose "Key [$($Property.Name)] is a Ordered Dictionary" Write-Verbose "Key [$($Property.Name)] is a Ordered Dictionary"
@@ -33,7 +33,7 @@
$Output.($Property.Name) = Merge-ConfigurationData -Template $Template.$($Property.Name) -Deployment $Deployment.$($Property.Name) -Output $Output.$($Property.Name) $Output.($Property.Name) = Merge-ConfigurationData -Template $Template.$($Property.Name) -Deployment $Deployment.$($Property.Name) -Output $Output.$($Property.Name)
}else{ }else{
Write-Verbose "Key [$($Property.Name)] is not present in Deployment Data" Write-Verbose "Key [$($Property.Name)] is not present in Deployment Data"
$Output.Add($($Property.Name),$Template.$($Property.Name)) $Output.Add($($Property.Name),(Copy-ConfigurationDataValue -Value $Template.$($Property.Name)))
} }
}elseif($Property.Value -is [System.Array]){ }elseif($Property.Value -is [System.Array]){
Write-Verbose "$($Property.Name) is ein Array" Write-Verbose "$($Property.Name) is ein Array"
@@ -41,25 +41,56 @@
Write-Verbose "Total Items in Deployment Array [$($Deployment.$($Property.Name).Count)]" Write-Verbose "Total Items in Deployment Array [$($Deployment.$($Property.Name).Count)]"
if($null -ne $Deployment.$($Property.Name)){ if($null -ne $Deployment.$($Property.Name)){
Write-Verbose "Array is defined in Deployment" Write-Verbose "Array is defined in Deployment"
for($i=0;$i -lt $Property.Value.Count; $i++){
$TemplateItems = for($i=0;$i -lt $Property.Value.Count; $i++){
$SearchItem = $($Property.Value[$i].GetEnumerator() | Where-Object {($_.Value -is [String]) -and ($_.Name -like "*Name")})[0] $SearchKeyNames = @(Get-ConfigurationDataArrayMergeKeyNames -ArrayName $Property.Name -Item $Property.Value[$i])
if($($Deployment.$($Property.Name) | ? { $_.($SearchItem.Name) -eq $SearchItem.Value })){ [PSCustomObject]@{
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 Value = $Property.Value[$i]
SearchKeyNames = $SearchKeyNames
IsWildcard = Test-ConfigurationDataItemWildcard -Item $Property.Value[$i] -KeyNames $SearchKeyNames
}
}
$TemplateItems = @($TemplateItems | Where-Object { -not $_.IsWildcard }) + @($TemplateItems | Where-Object { $_.IsWildcard })
foreach($TemplateItem in $TemplateItems){
$SearchKeyNames = @($TemplateItem.SearchKeyNames)
if($SearchKeyNames.Count -eq 0){
Write-Verbose "No matching name key found for item in [$($Property.Name)]"
$Output.$($Property.Name) += ,(Copy-ConfigurationDataValue -Value $TemplateItem.Value)
continue
}
if($TemplateItem.IsWildcard){
$MatchingDeploymentItems = @($Deployment.$($Property.Name) | Where-Object { Test-ConfigurationDataItemHasKeys -Item $_ -KeyNames $SearchKeyNames })
}else{ }else{
Write-Verbose "Pair $($Key.Name) - $($Key.Value) not present" $MatchingDeploymentItems = @($Deployment.$($Property.Name) | Where-Object { Test-ConfigurationDataItemKeyMatch -Left $_ -Right $TemplateItem.Value -KeyNames $SearchKeyNames })
$Output.$($Property.Name) += $Property.Value[$i] }
if($MatchingDeploymentItems.Count -gt 0){
foreach($DeploymentItem in $MatchingDeploymentItems){
$OutputItem = @($Output.$($Property.Name) | Where-Object { Test-ConfigurationDataItemKeyMatch -Left $_ -Right $DeploymentItem -KeyNames $SearchKeyNames })[0]
Merge-ConfigurationData -Template $TemplateItem.Value -Deployment $DeploymentItem -Output $OutputItem | Out-Null
}
}else{
if($TemplateItem.IsWildcard){
Write-Verbose "Wildcard item [$(Format-ConfigurationDataMergeKey -Item $TemplateItem.Value -KeyNames $SearchKeyNames)] in [$($Property.Name)] matched no deployment items"
}else{
Write-Verbose "Pair [$(Format-ConfigurationDataMergeKey -Item $TemplateItem.Value -KeyNames $SearchKeyNames)] not present"
$Output.$($Property.Name) += ,(Copy-ConfigurationDataValue -Value $TemplateItem.Value)
}
} }
} }
}else{ }else{
Write-Verbose "Array is not defined in Deployment" Write-Verbose "Array is not defined in Deployment"
$Output.$($Property.Name) = $Template.$($Property.Name) $Output.$($Property.Name) = Copy-ConfigurationDataValue -Value $Template.$($Property.Name)
} }
}else{ }else{
Write-Verbose "$($Property.Name) is a String or Integer Value" Write-Verbose "$($Property.Name) is a String or Integer Value"
if($null -eq $Deployment.$($Property.Name)){ if($null -eq $Deployment.$($Property.Name)){
$Output.Add($Property.Name,$Template.($Property.Name)) $Output.Add($Property.Name,(Copy-ConfigurationDataValue -Value $Template.($Property.Name)))
}elseif($Deployment.$($Property.Name) -ne $Property.Value){ }elseif($Deployment.$($Property.Name) -ne $Property.Value){
@@ -67,4 +98,230 @@
} }
} }
return $Output return $Output
} }
function Copy-ConfigurationDataValue {
[CmdletBinding()]
Param(
[AllowNull()]
$Value
)
if($null -eq $Value){
return $null
}
if($Value -is [System.Collections.Specialized.OrderedDictionary]){
$Copy = [ordered]@{}
foreach($Entry in $Value.GetEnumerator()){
$Copy[$Entry.Name] = Copy-ConfigurationDataValue -Value $Entry.Value
}
return $Copy
}
if($Value -is [System.Collections.Hashtable]){
$Copy = @{}
foreach($Entry in $Value.GetEnumerator()){
$Copy[$Entry.Name] = Copy-ConfigurationDataValue -Value $Entry.Value
}
return $Copy
}
if($Value -is [System.Array]){
$Copy = @()
foreach($Item in $Value){
$Copy += ,(Copy-ConfigurationDataValue -Value $Item)
}
return ,$Copy
}
return $Value
}
function Get-ConfigurationDataArraySearchItem {
[CmdletBinding()]
Param(
[AllowNull()]
$Item
)
if($null -eq $Item){
return $null
}
if(-not (
($Item -is [System.Collections.Hashtable]) -or
($Item -is [System.Collections.Specialized.OrderedDictionary])
)){
return $null
}
return @(
$Item.GetEnumerator() |
Where-Object { ($_.Value -is [String]) -and ($_.Name -like "*Name") } |
Select-Object -First 1
)[0]
}
function Get-ConfigurationDataArrayMergeKeyNames {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[String]
$ArrayName,
[AllowNull()]
$Item
)
$MergeKeyMap = @{
Instances = @('Name')
ConfigurationOptions = @('OptionName')
AdditionalScripts = @('ScriptName')
Templates = @('TemplateName')
AllNodes = @('NodeName')
Registry = @('Key','ValueName')
}
if($MergeKeyMap.ContainsKey($ArrayName)){
return $MergeKeyMap[$ArrayName]
}
$SearchItem = Get-ConfigurationDataArraySearchItem -Item $Item
if($null -ne $SearchItem){
return @($SearchItem.Name)
}
return @()
}
function Test-ConfigurationDataItemContainsKey {
[CmdletBinding()]
Param(
[AllowNull()]
$Item,
[Parameter(Mandatory=$true)]
[String]
$KeyName
)
if($null -eq $Item){
return $false
}
if($Item -is [System.Collections.IDictionary]){
return $Item.Contains($KeyName)
}
return $null -ne $Item.PSObject.Properties[$KeyName]
}
function Get-ConfigurationDataItemValue {
[CmdletBinding()]
Param(
[AllowNull()]
$Item,
[Parameter(Mandatory=$true)]
[String]
$KeyName
)
if(-not (Test-ConfigurationDataItemContainsKey -Item $Item -KeyName $KeyName)){
return $null
}
if($Item -is [System.Collections.IDictionary]){
return $Item[$KeyName]
}
return $Item.$KeyName
}
function Test-ConfigurationDataItemHasKeys {
[CmdletBinding()]
Param(
[AllowNull()]
$Item,
[Parameter(Mandatory=$true)]
[String[]]
$KeyNames
)
foreach($KeyName in $KeyNames){
if(-not (Test-ConfigurationDataItemContainsKey -Item $Item -KeyName $KeyName)){
return $false
}
}
return $true
}
function Test-ConfigurationDataItemKeyMatch {
[CmdletBinding()]
Param(
[AllowNull()]
$Left,
[AllowNull()]
$Right,
[Parameter(Mandatory=$true)]
[String[]]
$KeyNames
)
if($KeyNames.Count -eq 0){
return $false
}
foreach($KeyName in $KeyNames){
if(-not (Test-ConfigurationDataItemContainsKey -Item $Left -KeyName $KeyName)){
return $false
}
if(-not (Test-ConfigurationDataItemContainsKey -Item $Right -KeyName $KeyName)){
return $false
}
if((Get-ConfigurationDataItemValue -Item $Left -KeyName $KeyName) -ne (Get-ConfigurationDataItemValue -Item $Right -KeyName $KeyName)){
return $false
}
}
return $true
}
function Test-ConfigurationDataItemWildcard {
[CmdletBinding()]
Param(
[AllowNull()]
$Item,
[Parameter(Mandatory=$true)]
[String[]]
$KeyNames
)
if($KeyNames.Count -ne 1){
return $false
}
if(-not (Test-ConfigurationDataItemContainsKey -Item $Item -KeyName $KeyNames[0])){
return $false
}
return (Get-ConfigurationDataItemValue -Item $Item -KeyName $KeyNames[0]) -eq "*"
}
function Format-ConfigurationDataMergeKey {
[CmdletBinding()]
Param(
[AllowNull()]
$Item,
[Parameter(Mandatory=$true)]
[String[]]
$KeyNames
)
$Pairs = foreach($KeyName in $KeyNames){
"$KeyName=$(Get-ConfigurationDataItemValue -Item $Item -KeyName $KeyName)"
}
return ($Pairs -join ", ")
}

View File

@@ -1,111 +0,0 @@
@{
Templates = @(
@{
TemplateName = "HZD Template"
TemplatePath = "./Configurations/HZD.psd1"
},
@{
TemplateName = "SQL Server Template"
TemplatePath = "./Configurations/Services/Template-SQLServer.psd1"
},
@{
TemplateName = "Umgebungs Template"
TemplatePath = "./Configurations/Umgebungen/Template-Test.psd1"
}
)
AllNodes = @(
@{
NodeName = "JURZMAZSSQL901"
}
)
NonNodeData =@{
Services = @{
SQLServer = @{
Instances = @(
@{
Name = 'MSSQLSERVER'
ServiceAccounts = @{
SQLEngineAccount = @{
ServiceAccountName = "gmsaE2Af901"
AccountType = "Group"
Path = "OU=DBA,OU=Dienste_Verfahren,OU=Administration,DC=justiz,DC=hessen,DC=de"
ManagedPasswordPrincipals = @(
@{
GroupName = "sicE2AfE2ADB901"
Path = "OU=DBA,OU=Dienste_Verfahren,OU=Administration,DC=justiz,DC=hessen,DC=de"
}
)
}
SQLAgentAccount = @{
ServiceAccountName = "gmsaE2Aa901"
AccountType = "Group"
Path = "OU=DBA,OU=Dienste_Verfahren,OU=Administration,DC=justiz,DC=hessen,DC=de"
ManagedPasswordPrincipals = @(
@{
GroupName = "sicE2AfE2ADB901"
Path = "OU=DBA,OU=Dienste_Verfahren,OU=Administration,DC=justiz,DC=hessen,DC=de"
}
)
}
}
AlwaysOn = @{
StartIndex = "B"
AlwaysOnGroups = @(
@{
Name = "TestAG"
FailoverMode ="Automatic"
SeedingMode = "Automatic"
Listener = @{
Provision = $true
IpAddress = "'10.96.x.x/255.255.255.0','10.96.x.x/255.255.255.0'"
Port = 1433
}
}
)
}
ConfigurationOptions= @()
AdditionalScripts = @()
},
@{
Name = 'MSSQLSERVERTEST'
ServiceAccounts = @{
SQLEngineAccount = @{
ServiceAccountName = "gmsaE2Af901"
AccountType = "Group"
Path = "OU=DBA,OU=Dienste_Verfahren,OU=Administration,DC=justiz,DC=hessen,DC=de"
ManagedPasswordPrincipals = @(
@{
GroupName = "sicE2AfE2ADB901"
Path = "OU=DBA,OU=Dienste_Verfahren,OU=Administration,DC=justiz,DC=hessen,DC=de"
}
)
}
SQLAgentAccount = @{
ServiceAccountName = "gmsaE2Aa901"
AccountType = "Group"
Path = "OU=DBA,OU=Dienste_Verfahren,OU=Administration,DC=justiz,DC=hessen,DC=de"
ManagedPasswordPrincipals = @(
@{
GroupName = "sicE2AfE2ADB901"
Path = "OU=DBA,OU=Dienste_Verfahren,OU=Administration,DC=justiz,DC=hessen,DC=de"
}
)
}
}
ConfigurationOptions= @()
AdditionalScripts = @()
}
)
}
}
}
}

View File

@@ -1,157 +0,0 @@
@{
NonNodeData =@{
Services = @{
SQLServer = @{
General = @{
Version = ""
Release = "2022"
SourcePath = "\\JURZMAZSFIL02.justiz.hessen.de\DbaDSCSources\Binaries"
DestinationPath = "C:\HZD\SQL_Install"
}
Basic = @{
Registry = @(
@{
Key = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa"
ValueName = "DisableLoopbackCheck"
ValueData = 1
ValueType = "Dword"
},
@{
Ensure = "Present"
Key = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL16.MSSQLSERVER\SQLServerAgent"
ValueName = "MsxEncryptChannelOptions"
ValueData = 1
ValueType = "Dword"
}
@{
Ensure = 'Present'
Key = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL16.MSSQLSERVER\SQLServerAgent'
ValueName = 'ErrorLogFile'
ValueData = 'D:\MSSQL16.MSSQLSERVER\MSSQL\Log\SQLAGENT.OUT'
ValueType = 'String'
},
@{
Ensure = 'Present'
Key = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL16.MSSQLSERVER\SQLServerAgent'
ValueName = 'WorkingDirectory'
ValueData = 'D:\MSSQL16.MSSQLSERVER\MSSQL\JOBS'
ValueType = 'String'
}
)
WindowsFeatures = @(
@{
Name = "RSAT-AD-PowerShell"
}
)
Modules = @(
@{
Name = "SQLServer"
AllowClobber = $true
}
)
}
Instances = @(
@{
Name = '*'
Features = 'SQLENGINE,FULLTEXT'
SQLSysAdminAccounts = 'sicDBServer_ServerAdmins'
Directories = @{
InstallSharedDir = 'D:\Microsoft SQL Server'
InstallSharedWOWDir = 'D:\Microsoft SQL Server (x86)'
InstanceDir = 'D:\Microsoft SQL Server'
InstallSQLDataDir = 'D:'
SQLSysAdminAccounts = 'sicDBServer_ServerAdmins'
SQLBackupDir = '\\JURZMAZSFIL02.justiz.hessen.de\DbaDSCSources\Backups'
SQLUserDBDir = ''
SQLUserDBLogDir = ''
SQLTempDBDir = ''
SQLTempDBLogDir = ''
}
Drives = @{
}
MountPoints = @{
}
Memory = @{
UseDynamic = $true
minValue = 1024
maxValue = 8192
}
ServiceAccounts = @{
}
AlwaysOn = @{
}
ConfigurationOptions= @(
@{
OptionName = 'show advanced options'
OptionValue = '1'
},
@{
OptionName = 'cost threshold for parallelism'
OptionValue = '50'
},
@{
OptionName = 'blocked process threshold (s)'
OptionValue = '30'
},
@{
OptionName = 'backup compression default'
OptionValue = '1'
}
)
AdditionalScripts = @(
@{
ScriptName = 'AdminDB'
ScriptPath = '\\JURZMAZSFIL02.justiz.hessen.de\DbaDSCSources\SQL_Scripts\AdminDB'
DependsOn = '[SqlSetup]Instance-MSSQLSERVER'
},
@{
ScriptName = 'RenameSA'
ScriptPath = '\\JURZMAZSFIL02.justiz.hessen.de\DbaDSCSources\SQL_Scripts\RenameSA'
DependsOn = '[SqlScript]AdminDB'
},
@{
ScriptName = 'Maintenance_Solution'
ScriptPath = '\\JURZMAZSFIL02.justiz.hessen.de\DbaDSCSources\SQL_Scripts\Maintenance_Solutions'
DependsOn = '[SqlScript]RenameSA'
},
@{
ScriptName = 'WhoIsActive'
ScriptPath = '\\JURZMAZSFIL02.justiz.hessen.de\DbaDSCSources\SQL_Scripts\WhoIsActive_Monitoring'
DependsOn = '[SqlScript]Maintenance_Solution'
},
@{
ScriptName = 'Alerts'
ScriptPath = '\\JURZMAZSFIL02.justiz.hessen.de\DbaDSCSources\SQL_Scripts\Alerts_Email'
DependsOn = '[SqlScript]WhoIsActive'
},
@{
ScriptName = 'TempDB'
ScriptPath = '\\JURZMAZSFIL02.justiz.hessen.de\DbaDSCSources\SQL_Scripts\TempDB_Size'
DependsOn = '[SqlScript]Alerts'
}
)
}
)
}
}
}
}