Compare commits
2 Commits
8c6642672e
...
a96fb5bd07
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a96fb5bd07 | ||
|
|
086020c3df |
512
.tests/Resolve-DSCConfigurationData.Tests.ps1
Normal file
512
.tests/Resolve-DSCConfigurationData.Tests.ps1
Normal file
@@ -0,0 +1,512 @@
|
|||||||
|
$script:ModuleRoot = Split-Path -Path $PSScriptRoot -Parent
|
||||||
|
Import-Module (Join-Path -Path $script:ModuleRoot -ChildPath "Resolve-DSCConfigurationData.psd1") -Force
|
||||||
|
|
||||||
|
Describe "Resolve-DSCConfigurationData" {
|
||||||
|
It "resolves parameters using Value before DefaultValue" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
Name = @{
|
||||||
|
DefaultValue = "Default"
|
||||||
|
Value = "Deployment"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Resources = @{
|
||||||
|
Value = "[parameters('Name')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Result = Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData
|
||||||
|
|
||||||
|
$Result.Resources.Value | Should Be "Deployment"
|
||||||
|
}
|
||||||
|
|
||||||
|
It "allows parameter values listed in AllowedValues" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
Stage = @{
|
||||||
|
Value = "Test"
|
||||||
|
AllowedValues = @(
|
||||||
|
"Install",
|
||||||
|
"Test",
|
||||||
|
"Release"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Resources = @{
|
||||||
|
Stage = "[parameters('Stage')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Result = Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData
|
||||||
|
|
||||||
|
$Result.Resources.Stage | Should Be "Test"
|
||||||
|
}
|
||||||
|
|
||||||
|
It "validates DefaultValue against AllowedValues when Value is not set" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
Stage = @{
|
||||||
|
DefaultValue = "Release"
|
||||||
|
AllowedValues = @(
|
||||||
|
"Install",
|
||||||
|
"Test",
|
||||||
|
"Release"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Resources = @{
|
||||||
|
Stage = "[parameters('Stage')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Result = Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData
|
||||||
|
|
||||||
|
$Result.Resources.Stage | Should Be "Release"
|
||||||
|
}
|
||||||
|
|
||||||
|
It "throws when a parameter value is not listed in AllowedValues" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
Stage = @{
|
||||||
|
Value = "Production"
|
||||||
|
AllowedValues = @(
|
||||||
|
"Install",
|
||||||
|
"Test",
|
||||||
|
"Release"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Resources = @{
|
||||||
|
Stage = "[parameters('Stage')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData } | Should Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It "validates array parameter items against AllowedValues" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
ServerRoles = @{
|
||||||
|
Type = "array"
|
||||||
|
Value = @(
|
||||||
|
"WebFrontEnd",
|
||||||
|
"Application"
|
||||||
|
)
|
||||||
|
AllowedValues = @(
|
||||||
|
"WebFrontEnd",
|
||||||
|
"Application",
|
||||||
|
"Search"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Resources = @{
|
||||||
|
Roles = "[parameters('ServerRoles')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Result = Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData
|
||||||
|
|
||||||
|
$Result.Resources.Roles[0] | Should Be "WebFrontEnd"
|
||||||
|
$Result.Resources.Roles[1] | Should Be "Application"
|
||||||
|
}
|
||||||
|
|
||||||
|
It "throws when an array parameter item is not listed in AllowedValues" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
ServerRoles = @{
|
||||||
|
Type = "array"
|
||||||
|
Value = @(
|
||||||
|
"WebFrontEnd",
|
||||||
|
"InvalidRole"
|
||||||
|
)
|
||||||
|
AllowedValues = @(
|
||||||
|
"WebFrontEnd",
|
||||||
|
"Application",
|
||||||
|
"Search"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData } | Should Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It "validates required parameters" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
DatabasePrefix = @{
|
||||||
|
Type = "string"
|
||||||
|
Required = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData } | Should Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It "validates parameter length constraints" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
DatabasePrefix = @{
|
||||||
|
Value = "S"
|
||||||
|
MinLength = 2
|
||||||
|
MaxLength = 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData } | Should Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It "validates parameter patterns" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
DatabasePrefix = @{
|
||||||
|
Value = "Share Point"
|
||||||
|
Pattern = "^[A-Za-z][A-Za-z0-9_-]*$"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData } | Should Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It "validates supported parameter types" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
Name = @{
|
||||||
|
Type = "string"
|
||||||
|
Value = "SharePoint"
|
||||||
|
}
|
||||||
|
Port = @{
|
||||||
|
Type = "int"
|
||||||
|
Value = 1433
|
||||||
|
}
|
||||||
|
Enabled = @{
|
||||||
|
Type = "bool"
|
||||||
|
Value = $true
|
||||||
|
}
|
||||||
|
Roles = @{
|
||||||
|
Type = "array"
|
||||||
|
Value = @(
|
||||||
|
"WebFrontEnd",
|
||||||
|
"Application"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
SecretReference = @{
|
||||||
|
Type = "secureString"
|
||||||
|
Value = @{
|
||||||
|
SecretName = "SharePointFarmPassphrase"
|
||||||
|
}
|
||||||
|
Sensitive = $true
|
||||||
|
}
|
||||||
|
CredentialReference = @{
|
||||||
|
Type = "credential"
|
||||||
|
Value = @{
|
||||||
|
CredentialName = "SharePointSetup"
|
||||||
|
}
|
||||||
|
Sensitive = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Resources = @{
|
||||||
|
Name = "[parameters('Name')]"
|
||||||
|
Port = "[parameters('Port')]"
|
||||||
|
Enabled = "[parameters('Enabled')]"
|
||||||
|
RoleCount = "[length(parameters('Roles'))]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Result = Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData
|
||||||
|
|
||||||
|
$Result.Resources.Name | Should Be "SharePoint"
|
||||||
|
$Result.Resources.Port | Should Be 1433
|
||||||
|
$Result.Resources.Enabled | Should Be $true
|
||||||
|
$Result.Resources.RoleCount | Should Be 2
|
||||||
|
}
|
||||||
|
|
||||||
|
It "throws when parameter type validation fails" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
Port = @{
|
||||||
|
Type = "int"
|
||||||
|
Value = "1433"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData } | Should Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It "validates numeric ranges" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
Port = @{
|
||||||
|
Type = "int"
|
||||||
|
Value = 1433
|
||||||
|
MinValue = 1
|
||||||
|
MaxValue = 65535
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Resources = @{
|
||||||
|
Port = "[parameters('Port')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Result = Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData
|
||||||
|
|
||||||
|
$Result.Resources.Port | Should Be 1433
|
||||||
|
}
|
||||||
|
|
||||||
|
It "throws when numeric range validation fails" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
Port = @{
|
||||||
|
Type = "int"
|
||||||
|
Value = 70000
|
||||||
|
MinValue = 1
|
||||||
|
MaxValue = 65535
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData } | Should Throw
|
||||||
|
}
|
||||||
|
|
||||||
|
It "supports localized deprecated parameter messages" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
OldDatabasePrefix = @{
|
||||||
|
Value = "SharePoint"
|
||||||
|
Deprecated = @{
|
||||||
|
Message = @{
|
||||||
|
"de-DE" = "Der Parameter [OldDatabasePrefix] ist veraltet. Verwende [DatabasePrefix]."
|
||||||
|
"en-US" = "Parameter [OldDatabasePrefix] is deprecated. Use [DatabasePrefix]."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Resources = @{
|
||||||
|
Value = "[parameters('OldDatabasePrefix')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Warnings = @()
|
||||||
|
$Result = Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData -WarningVariable Warnings 3>$null
|
||||||
|
|
||||||
|
$Result.Resources.Value | Should Be "SharePoint"
|
||||||
|
$Warnings.Count | Should Be 1
|
||||||
|
([string]$Warnings[0]) | Should Match "OldDatabasePrefix"
|
||||||
|
}
|
||||||
|
|
||||||
|
It "resolves variables that reference parameters" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
Prefix = @{
|
||||||
|
Value = "SharePoint"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Variables = @{
|
||||||
|
ConfigDbName = "[concat(parameters('Prefix'), '_Farm_Config')]"
|
||||||
|
}
|
||||||
|
Resources = @{
|
||||||
|
DatabaseName = "[variables('ConfigDbName')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Result = Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData
|
||||||
|
|
||||||
|
$Result.Variables.ConfigDbName | Should Be "SharePoint_Farm_Config"
|
||||||
|
$Result.Resources.DatabaseName | Should Be "SharePoint_Farm_Config"
|
||||||
|
}
|
||||||
|
|
||||||
|
It "resolves nested functions" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
Prefix = @{
|
||||||
|
Value = "sharepoint"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Resources = @{
|
||||||
|
Name = "[concat(toUpper(parameters('Prefix')), '_Services')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Result = Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData
|
||||||
|
|
||||||
|
$Result.Resources.Name | Should Be "SHAREPOINT_Services"
|
||||||
|
}
|
||||||
|
|
||||||
|
It "resolves string helper functions" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Resources = @{
|
||||||
|
Lower = "[toLower('BGW-LAN')]"
|
||||||
|
Upper = "[toUpper('bgw-lan')]"
|
||||||
|
First = "[firstIndexOf('a', 'b', 'c')]"
|
||||||
|
Last = "[lastIndexOf('a', 'b', 'c')]"
|
||||||
|
Index = "[indexOf('BGW', 1)]"
|
||||||
|
Substring = "[substring('SharePoint', 5, 5)]"
|
||||||
|
Replace = "[replace('BGW-LAN', '-', '_')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Result = Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData
|
||||||
|
|
||||||
|
$Result.Resources.Lower | Should Be "bgw-lan"
|
||||||
|
$Result.Resources.Upper | Should Be "BGW-LAN"
|
||||||
|
$Result.Resources.First | Should Be "a"
|
||||||
|
$Result.Resources.Last | Should Be "c"
|
||||||
|
$Result.Resources.Index | Should Be "G"
|
||||||
|
$Result.Resources.Substring | Should Be "Point"
|
||||||
|
$Result.Resources.Replace | Should Be "BGW_LAN"
|
||||||
|
}
|
||||||
|
|
||||||
|
It "resolves formatting, fallback, and conditional functions" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
DatabasePrefix = @{
|
||||||
|
Value = "SharePoint"
|
||||||
|
}
|
||||||
|
DomainLabel = @{
|
||||||
|
Value = "LAN"
|
||||||
|
}
|
||||||
|
Stage = @{
|
||||||
|
Value = "Test"
|
||||||
|
}
|
||||||
|
OptionalValue = @{
|
||||||
|
Value = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Resources = @{
|
||||||
|
Formatted = "[format('{0}_{1}_{2}', parameters('DatabasePrefix'), parameters('DomainLabel'), parameters('Stage'))]"
|
||||||
|
Fallback = "[coalesce(parameters('OptionalValue'), 'DefaultValue')]"
|
||||||
|
Conditional = "[if(equals(parameters('Stage'), 'Test'), 'TST', 'PRD')]"
|
||||||
|
NotEquals = "[notEquals(parameters('Stage'), 'Prod')]"
|
||||||
|
AndValue = "[and(equals(parameters('Stage'), 'Test'), not(empty(parameters('DatabasePrefix'))))]"
|
||||||
|
OrValue = "[or(equals(parameters('Stage'), 'Prod'), equals(parameters('Stage'), 'Test'))]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Result = Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData
|
||||||
|
|
||||||
|
$Result.Resources.Formatted | Should Be "SharePoint_LAN_Test"
|
||||||
|
$Result.Resources.Fallback | Should Be "DefaultValue"
|
||||||
|
$Result.Resources.Conditional | Should Be "TST"
|
||||||
|
$Result.Resources.NotEquals | Should Be $true
|
||||||
|
$Result.Resources.AndValue | Should Be $true
|
||||||
|
$Result.Resources.OrValue | Should Be $true
|
||||||
|
}
|
||||||
|
|
||||||
|
It "resolves collection and string inspection functions" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
DomainFQDN = @{
|
||||||
|
Value = "bgw-online.de"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Resources = @{
|
||||||
|
Split = "[split(parameters('DomainFQDN'), '.')]"
|
||||||
|
Joined = "[join(split(parameters('DomainFQDN'), '.'), '_')]"
|
||||||
|
JoinedNotEmpty = "[joinNotEmpty('_', 'SharePoint', '', 'LAN', 'Test', '', 'Services')]"
|
||||||
|
Take = "[join(take(split(parameters('DomainFQDN'), '.'), 1), '_')]"
|
||||||
|
Skip = "[join(skip(split(parameters('DomainFQDN'), '.'), 1), '_')]"
|
||||||
|
First = "[first(split(parameters('DomainFQDN'), '.'))]"
|
||||||
|
Last = "[last(split(parameters('DomainFQDN'), '.'))]"
|
||||||
|
Unique = "[join(unique(split('SP.SP.SQL', '.')), '_')]"
|
||||||
|
Sort = "[join(sort(split('SQL.SP.APP', '.')), '_')]"
|
||||||
|
ContainsString = "[contains(parameters('DomainFQDN'), 'online')]"
|
||||||
|
ContainsArray = "[contains(split(parameters('DomainFQDN'), '.'), 'de')]"
|
||||||
|
StartsWith = "[startsWith(parameters('DomainFQDN'), 'bgw')]"
|
||||||
|
EndsWith = "[endsWith(parameters('DomainFQDN'), 'DE')]"
|
||||||
|
Length = "[length(split(parameters('DomainFQDN'), '.'))]"
|
||||||
|
Empty = "[empty('')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Result = Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData
|
||||||
|
|
||||||
|
$Result.Resources.Split[0] | Should Be "bgw-online"
|
||||||
|
$Result.Resources.Split[1] | Should Be "de"
|
||||||
|
$Result.Resources.Joined | Should Be "bgw-online_de"
|
||||||
|
$Result.Resources.JoinedNotEmpty | Should Be "SharePoint_LAN_Test_Services"
|
||||||
|
$Result.Resources.Take | Should Be "bgw-online"
|
||||||
|
$Result.Resources.Skip | Should Be "de"
|
||||||
|
$Result.Resources.First | Should Be "bgw-online"
|
||||||
|
$Result.Resources.Last | Should Be "de"
|
||||||
|
$Result.Resources.Unique | Should Be "SP_SQL"
|
||||||
|
$Result.Resources.Sort | Should Be "APP_SP_SQL"
|
||||||
|
$Result.Resources.ContainsString | Should Be $true
|
||||||
|
$Result.Resources.ContainsArray | Should Be $true
|
||||||
|
$Result.Resources.StartsWith | Should Be $true
|
||||||
|
$Result.Resources.EndsWith | Should Be $true
|
||||||
|
$Result.Resources.Length | Should Be 2
|
||||||
|
$Result.Resources.Empty | Should Be $true
|
||||||
|
}
|
||||||
|
|
||||||
|
It "resolves trim and padding functions" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Resources = @{
|
||||||
|
Trim = "[trim(' SharePoint ')]"
|
||||||
|
TrimStart = "[trimStart(' SharePoint')]"
|
||||||
|
TrimEnd = "[trimEnd('SharePoint ')]"
|
||||||
|
PadLeft = "[padLeft('1', 2, '0')]"
|
||||||
|
PadRight = "[padRight('SP', 4, '0')]"
|
||||||
|
DefaultIfEmpty = "[defaultIfEmpty('', 'SharePoint')]"
|
||||||
|
Sanitized = "[sanitizeName(' SharePoint LAN/Test DB ')]"
|
||||||
|
Normalized = "[normalizeSeparator('__SharePoint___LAN_Test__', '_')]"
|
||||||
|
Prefix = "[prefixIfNotEmpty('LAN', 'BGW-')]"
|
||||||
|
EmptyPrefix = "[prefixIfNotEmpty('', 'BGW-')]"
|
||||||
|
Suffix = "[suffixIfNotEmpty('SharePoint', '_DB')]"
|
||||||
|
EmptySuffix = "[suffixIfNotEmpty('', '_DB')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Result = Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData
|
||||||
|
|
||||||
|
$Result.Resources.Trim | Should Be "SharePoint"
|
||||||
|
$Result.Resources.TrimStart | Should Be "SharePoint"
|
||||||
|
$Result.Resources.TrimEnd | Should Be "SharePoint"
|
||||||
|
$Result.Resources.PadLeft | Should Be "01"
|
||||||
|
$Result.Resources.PadRight | Should Be "SP00"
|
||||||
|
$Result.Resources.DefaultIfEmpty | Should Be "SharePoint"
|
||||||
|
$Result.Resources.Sanitized | Should Be "SharePoint_LAN_Test_DB"
|
||||||
|
$Result.Resources.Normalized | Should Be "SharePoint_LAN_Test"
|
||||||
|
$Result.Resources.Prefix | Should Be "BGW-LAN"
|
||||||
|
$Result.Resources.EmptyPrefix | Should Be ""
|
||||||
|
$Result.Resources.Suffix | Should Be "SharePoint_DB"
|
||||||
|
$Result.Resources.EmptySuffix | Should Be ""
|
||||||
|
}
|
||||||
|
|
||||||
|
It "resolves values inside arrays recursively" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Parameters = @{
|
||||||
|
NodeName = @{
|
||||||
|
Value = "SP01"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AllNodes = @(
|
||||||
|
@{
|
||||||
|
NodeName = "[parameters('NodeName')]"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
$Result = Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData
|
||||||
|
|
||||||
|
$Result.AllNodes[0].NodeName | Should Be "SP01"
|
||||||
|
}
|
||||||
|
|
||||||
|
It "throws for circular variables" {
|
||||||
|
$ConfigurationData = @{
|
||||||
|
Variables = @{
|
||||||
|
A = "[variables('B')]"
|
||||||
|
B = "[variables('A')]"
|
||||||
|
}
|
||||||
|
Resources = @{
|
||||||
|
Value = "[variables('A')]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ Resolve-DSCConfigurationData -ConfigurationData $ConfigurationData } | Should Throw
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,6 +42,7 @@ function Assert-ConfigurationDataParameter {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Assert-ConfigurationDataParameterType -Name $Name -Definition $Definition -Value $Value
|
||||||
Assert-ConfigurationDataParameterAllowedValue -Name $Name -Definition $Definition -Value $Value
|
Assert-ConfigurationDataParameterAllowedValue -Name $Name -Definition $Definition -Value $Value
|
||||||
|
|
||||||
if(Test-ConfigurationDataMapContainsKey -Map $Definition -Key "MinLength"){
|
if(Test-ConfigurationDataMapContainsKey -Map $Definition -Key "MinLength"){
|
||||||
@@ -64,4 +65,20 @@ function Assert-ConfigurationDataParameter {
|
|||||||
throw "Parameter [$Name] value [$Value] does not match pattern [$Pattern]."
|
throw "Parameter [$Name] value [$Value] does not match pattern [$Pattern]."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Test-ConfigurationDataMapContainsKey -Map $Definition -Key "MinValue"){
|
||||||
|
Assert-ConfigurationDataParameterNumericValue -Name $Name -Value $Value
|
||||||
|
$MinValue = [decimal](Get-ConfigurationDataMapValue -Map $Definition -Key "MinValue")
|
||||||
|
if(([decimal]$Value) -lt $MinValue){
|
||||||
|
throw "Parameter [$Name] value [$Value] is less than MinValue [$MinValue]."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Test-ConfigurationDataMapContainsKey -Map $Definition -Key "MaxValue"){
|
||||||
|
Assert-ConfigurationDataParameterNumericValue -Name $Name -Value $Value
|
||||||
|
$MaxValue = [decimal](Get-ConfigurationDataMapValue -Map $Definition -Key "MaxValue")
|
||||||
|
if(([decimal]$Value) -gt $MaxValue){
|
||||||
|
throw "Parameter [$Name] value [$Value] is greater than MaxValue [$MaxValue]."
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,16 @@ function Assert-ConfigurationDataParameterAllowedValue {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($Value -is [System.Array] -and $Value -isnot [string]){
|
||||||
|
foreach($Item in @($Value)){
|
||||||
|
if($AllowedValues -notcontains $Item){
|
||||||
|
throw "Parameter [$Name] value [$Item] is not allowed. Allowed values are: $($AllowedValues -join ', ')."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if($AllowedValues -notcontains $Value){
|
if($AllowedValues -notcontains $Value){
|
||||||
throw "Parameter [$Name] value [$Value] is not allowed. Allowed values are: $($AllowedValues -join ', ')."
|
throw "Parameter [$Name] value [$Value] is not allowed. Allowed values are: $($AllowedValues -join ', ')."
|
||||||
}
|
}
|
||||||
|
|||||||
21
Private/Assert-ConfigurationDataParameterNumericValue.ps1
Normal file
21
Private/Assert-ConfigurationDataParameterNumericValue.ps1
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
function Assert-ConfigurationDataParameterNumericValue {
|
||||||
|
[CmdletBinding()]
|
||||||
|
Param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]
|
||||||
|
$Name,
|
||||||
|
|
||||||
|
[AllowNull()]
|
||||||
|
$Value
|
||||||
|
)
|
||||||
|
|
||||||
|
if($null -eq $Value -or $Value -is [bool] -or ($Value -isnot [ValueType])){
|
||||||
|
throw "Parameter [$Name] value [$Value] is not numeric."
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
[void]([decimal]$Value)
|
||||||
|
} catch {
|
||||||
|
throw "Parameter [$Name] value [$Value] is not numeric."
|
||||||
|
}
|
||||||
|
}
|
||||||
61
Private/Assert-ConfigurationDataParameterType.ps1
Normal file
61
Private/Assert-ConfigurationDataParameterType.ps1
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
function Assert-ConfigurationDataParameterType {
|
||||||
|
[CmdletBinding()]
|
||||||
|
Param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]
|
||||||
|
$Name,
|
||||||
|
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
$Definition,
|
||||||
|
|
||||||
|
[AllowNull()]
|
||||||
|
$Value
|
||||||
|
)
|
||||||
|
|
||||||
|
if(-not (Test-ConfigurationDataMapContainsKey -Map $Definition -Key "Type")){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$TypeName = ([string](Get-ConfigurationDataMapValue -Map $Definition -Key "Type")).ToLowerInvariant()
|
||||||
|
|
||||||
|
switch($TypeName){
|
||||||
|
"string" {
|
||||||
|
if($Value -isnot [string]){
|
||||||
|
throw "Parameter [$Name] expects type [string], but received [$($Value.GetType().Name)]."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ $_ -in @("int", "integer") } {
|
||||||
|
if(-not (Test-ConfigurationDataValueIsInteger -Value $Value)){
|
||||||
|
throw "Parameter [$Name] expects type [int], but received [$($Value.GetType().Name)]."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ $_ -in @("bool", "boolean") } {
|
||||||
|
if($Value -isnot [bool]){
|
||||||
|
throw "Parameter [$Name] expects type [bool], but received [$($Value.GetType().Name)]."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"array" {
|
||||||
|
if($Value -isnot [System.Array] -or $Value -is [string]){
|
||||||
|
throw "Parameter [$Name] expects type [array], but received [$($Value.GetType().Name)]."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ $_ -in @("hashtable", "object") } {
|
||||||
|
if(-not (Test-ConfigurationDataMap -Value $Value)){
|
||||||
|
throw "Parameter [$Name] expects type [hashtable], but received [$($Value.GetType().Name)]."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"securestring" {
|
||||||
|
if(($Value -isnot [string]) -and ($Value -isnot [System.Security.SecureString]) -and (-not (Test-ConfigurationDataMap -Value $Value))){
|
||||||
|
throw "Parameter [$Name] expects type [secureString], but received [$($Value.GetType().Name)]."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"credential" {
|
||||||
|
if(($Value -isnot [System.Management.Automation.PSCredential]) -and (-not (Test-ConfigurationDataMap -Value $Value))){
|
||||||
|
throw "Parameter [$Name] expects type [credential], but received [$($Value.GetType().Name)]."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
throw "Parameter [$Name] uses unsupported type [$TypeName]."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
Private/Test-ConfigurationDataValueIsInteger.ps1
Normal file
20
Private/Test-ConfigurationDataValueIsInteger.ps1
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
function Test-ConfigurationDataValueIsInteger {
|
||||||
|
[CmdletBinding()]
|
||||||
|
Param(
|
||||||
|
[AllowNull()]
|
||||||
|
$Value
|
||||||
|
)
|
||||||
|
|
||||||
|
if($null -eq $Value -or $Value -is [bool]){
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($Value -is [byte]) -or
|
||||||
|
($Value -is [sbyte]) -or
|
||||||
|
($Value -is [int16]) -or
|
||||||
|
($Value -is [uint16]) -or
|
||||||
|
($Value -is [int]) -or
|
||||||
|
($Value -is [uint32]) -or
|
||||||
|
($Value -is [long]) -or
|
||||||
|
($Value -is [uint64])
|
||||||
|
}
|
||||||
121
Readme.md
121
Readme.md
@@ -1,4 +1,4 @@
|
|||||||
# Resolve-DSCConfigurationData
|
# Resolve-DSCConfigurationData
|
||||||
|
|
||||||
`Resolve-DSCConfigurationData` resolves parameter, variable, and expression references in DSC configuration data.
|
`Resolve-DSCConfigurationData` resolves parameter, variable, and expression references in DSC configuration data.
|
||||||
|
|
||||||
@@ -47,6 +47,10 @@ This block shows all currently supported parameter properties.
|
|||||||
MinLength = 2
|
MinLength = 2
|
||||||
MaxLength = 32
|
MaxLength = 32
|
||||||
|
|
||||||
|
# Optional numeric range validation. Applies to numeric values such as Type = 'int'.
|
||||||
|
MinValue = 1
|
||||||
|
MaxValue = 65535
|
||||||
|
|
||||||
# Optional regex validation.
|
# Optional regex validation.
|
||||||
Pattern = '^[A-Za-z][A-Za-z0-9_-]*$'
|
Pattern = '^[A-Za-z][A-Za-z0-9_-]*$'
|
||||||
|
|
||||||
@@ -75,11 +79,72 @@ This block shows all currently supported parameter properties.
|
|||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
- `Value` wins over `DefaultValue`.
|
- `Value` wins over `DefaultValue`.
|
||||||
- `Required`, `AllowedValues`, `MinLength`, `MaxLength`, and `Pattern` are validated by the resolver.
|
- `Type`, `Required`, `AllowedValues`, `MinLength`, `MaxLength`, `MinValue`, `MaxValue`, and `Pattern` are validated by the resolver.
|
||||||
|
- `AllowedValues` validates scalar values directly and array values item by item.
|
||||||
- `Sensitive` is currently metadata only.
|
- `Sensitive` is currently metadata only.
|
||||||
- `Deprecated.Message` can be a string or a localized hashtable.
|
- `Deprecated.Message` can be a string or a localized hashtable.
|
||||||
- Optional string parameters can allow empty values with a pattern like `'^$|^[A-Za-z][A-Za-z0-9_-]*$'`.
|
- Optional string parameters can allow empty values with a pattern like `'^$|^[A-Za-z][A-Za-z0-9_-]*$'`.
|
||||||
|
|
||||||
|
Supported parameter types:
|
||||||
|
|
||||||
|
- `string`
|
||||||
|
- `int` / `integer`
|
||||||
|
- `bool` / `boolean`
|
||||||
|
- `array`
|
||||||
|
- `hashtable` / `object`
|
||||||
|
- `secureString`
|
||||||
|
- `credential`
|
||||||
|
|
||||||
|
`secureString` and `credential` are intended for secret references, not raw secrets in PSD1 files:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
FarmPassphrase = @{
|
||||||
|
Type = 'secureString'
|
||||||
|
Required = $true
|
||||||
|
Sensitive = $true
|
||||||
|
Value = @{
|
||||||
|
SecretName = 'SharePointFarmPassphrase'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetupCredential = @{
|
||||||
|
Type = 'credential'
|
||||||
|
Required = $true
|
||||||
|
Sensitive = $true
|
||||||
|
Value = @{
|
||||||
|
CredentialName = 'SharePointSetup'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Array values can be restricted item by item:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
ServerRoles = @{
|
||||||
|
Type = 'array'
|
||||||
|
Value = @(
|
||||||
|
'WebFrontEnd',
|
||||||
|
'Application'
|
||||||
|
)
|
||||||
|
AllowedValues = @(
|
||||||
|
'WebFrontEnd',
|
||||||
|
'Application',
|
||||||
|
'Search'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Numeric values can be restricted with `MinValue` and `MaxValue`:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
SqlPort = @{
|
||||||
|
Type = 'int'
|
||||||
|
DefaultValue = 1433
|
||||||
|
MinValue = 1
|
||||||
|
MaxValue = 65535
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Variable Example
|
## Variable Example
|
||||||
|
|
||||||
Variables may reference parameters and other variables. Nested variable references are supported. Circular references are rejected.
|
Variables may reference parameters and other variables. Nested variable references are supported. Circular references are rejected.
|
||||||
@@ -93,7 +158,7 @@ Variables may reference parameters and other variables. Nested variable referenc
|
|||||||
}
|
}
|
||||||
DomainLabel = @{
|
DomainLabel = @{
|
||||||
Type = 'string'
|
Type = 'string'
|
||||||
Value = 'LAN'
|
Value = 'corp'
|
||||||
}
|
}
|
||||||
Landscape = @{
|
Landscape = @{
|
||||||
Type = 'string'
|
Type = 'string'
|
||||||
@@ -122,9 +187,9 @@ Example output:
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
StageCode : TST
|
StageCode : TST
|
||||||
DatabasePrefix : SharePoint_LAN_TST
|
DatabasePrefix : SharePoint_corp_TST
|
||||||
ServiceDbPrefix : SharePoint_LAN_TST_Services
|
ServiceDbPrefix : SharePoint_corp_TST_Services
|
||||||
ConfigDbName : SharePoint_LAN_TST_Farm_Config
|
ConfigDbName : SharePoint_corp_TST_Farm_Config
|
||||||
```
|
```
|
||||||
|
|
||||||
## Functions
|
## Functions
|
||||||
@@ -149,12 +214,12 @@ ConfigDbName : SharePoint_LAN_TST_Farm_Config
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
"[format('{0}_{1}_{2}', parameters('DatabasePrefix'), parameters('DomainLabel'), parameters('Landscape'))]"
|
"[format('{0}_{1}_{2}', parameters('DatabasePrefix'), parameters('DomainLabel'), parameters('Landscape'))]"
|
||||||
# SharePoint_LAN_Test
|
# SharePoint_corp_Test
|
||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
"[joinNotEmpty('_', parameters('DatabasePrefix'), parameters('DomainLabel'), '', 'Services')]"
|
"[joinNotEmpty('_', parameters('DatabasePrefix'), parameters('DomainLabel'), '', 'Services')]"
|
||||||
# SharePoint_LAN_Services
|
# SharePoint_corp_Services
|
||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
@@ -185,13 +250,13 @@ ConfigDbName : SharePoint_LAN_TST_Farm_Config
|
|||||||
### Case And Text
|
### Case And Text
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
"[toLower('BGW-LAN')]"
|
"[toLower('Contoso-CORP')]"
|
||||||
# bgw-lan
|
# contoso-corp
|
||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
"[toUpper('bgw-lan')]"
|
"[toUpper('contoso-corp')]"
|
||||||
# BGW-LAN
|
# CONTOSO-CORP
|
||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
@@ -201,8 +266,8 @@ ConfigDbName : SharePoint_LAN_TST_Farm_Config
|
|||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
"[replace('BGW-LAN', '-', '_')]"
|
"[replace('Contoso-CORP', '-', '_')]"
|
||||||
# BGW_LAN
|
# Contoso_CORP
|
||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
@@ -211,7 +276,7 @@ ConfigDbName : SharePoint_LAN_TST_Farm_Config
|
|||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
"[indexOf('BGW', 1)]"
|
"[indexOf('CON', 1)]"
|
||||||
# G
|
# G
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -228,23 +293,23 @@ ConfigDbName : SharePoint_LAN_TST_Farm_Config
|
|||||||
### Name Cleanup
|
### Name Cleanup
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
"[sanitizeName(' SharePoint LAN/Test DB ')]"
|
"[sanitizeName(' SharePoint corp/Test DB ')]"
|
||||||
# SharePoint_LAN_Test_DB
|
# SharePoint_corp_Test_DB
|
||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
"[sanitizeName(' SharePoint LAN/Test DB ', '-')]"
|
"[sanitizeName(' SharePoint corp/Test DB ', '-')]"
|
||||||
# SharePoint-LAN-Test-DB
|
# SharePoint-corp-Test-DB
|
||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
"[normalizeSeparator('__SharePoint___LAN_Test__', '_')]"
|
"[normalizeSeparator('__SharePoint___corp_Test__', '_')]"
|
||||||
# SharePoint_LAN_Test
|
# SharePoint_corp_Test
|
||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
"[prefixIfNotEmpty('LAN', 'BGW-')]"
|
"[prefixIfNotEmpty('corp', 'Contoso-')]"
|
||||||
# BGW-LAN
|
# Contoso-corp
|
||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
@@ -256,17 +321,17 @@ ConfigDbName : SharePoint_LAN_TST_Farm_Config
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
"[split(parameters('DomainFQDN'), '.')]"
|
"[split(parameters('DomainFQDN'), '.')]"
|
||||||
# @('bgw-online', 'de')
|
# @('contoso', 'com')
|
||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
"[join(split(parameters('DomainFQDN'), '.'), '_')]"
|
"[join(split(parameters('DomainFQDN'), '.'), '_')]"
|
||||||
# bgw-online_de
|
# contoso_com
|
||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
"[first(split(parameters('DomainFQDN'), '.'))]"
|
"[first(split(parameters('DomainFQDN'), '.'))]"
|
||||||
# bgw-online
|
# contoso
|
||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
@@ -276,7 +341,7 @@ ConfigDbName : SharePoint_LAN_TST_Farm_Config
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
"[take(split(parameters('DomainFQDN'), '.'), 1)]"
|
"[take(split(parameters('DomainFQDN'), '.'), 1)]"
|
||||||
# @('bgw-online')
|
# @('contoso')
|
||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
@@ -307,7 +372,7 @@ ConfigDbName : SharePoint_LAN_TST_Farm_Config
|
|||||||
```
|
```
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
"[startsWith(parameters('DomainFQDN'), 'bgw')]"
|
"[startsWith(parameters('DomainFQDN'), 'contoso')]"
|
||||||
# True
|
# True
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user