# Resolve-DSCConfigurationData `Resolve-DSCConfigurationData` resolves parameter, variable, and expression references in DSC configuration data. Typical flow: ```powershell $merged = Merge-DSCConfigurationData -Template $service -Deployment $environment $resolved = Resolve-DSCConfigurationData -ConfigurationData $merged ``` Expressions use an ARM-like syntax: ```powershell "[parameters('DatabasePrefix')]" "[variables('ServiceDbPrefix')]" "[concat(parameters('DatabasePrefix'), '_', parameters('ServiceDatabaseSegment'))]" ``` ## Parameter Example This block shows all currently supported parameter properties. ```powershell @{ Parameters = @{ DatabasePrefix = @{ Type = 'string' # Optional explicit value. If Value is present, it wins over DefaultValue. Value = 'SharePoint' # Used when Value is not present. DefaultValue = 'SharePoint' # If true, Value or DefaultValue must be present and not empty. Required = $true # Optional fixed set of valid values. AllowedValues = @( 'SharePoint', 'ProjectServer', 'Search' ) # Optional string length validation. MinLength = 2 MaxLength = 32 # Optional numeric range validation. Applies to numeric values such as Type = 'int'. MinValue = 1 MaxValue = 65535 # Optional regex validation. Pattern = '^[A-Za-z][A-Za-z0-9_-]*$' # Metadata for later reporting/output tooling. The resolver does not mask values yet. Sensitive = $false # Emits a warning when the parameter is present. Deprecated = @{ Message = @{ 'de-DE' = 'Der Parameter [DatabasePrefix] ist veraltet. Verwende [SharePointDatabasePrefix].' 'en-US' = 'Parameter [DatabasePrefix] is deprecated. Use [SharePointDatabasePrefix].' } } Metadata = @{ Description = @{ 'de-DE' = 'Praefix fuer alle von der SharePoint-Farm angelegten Datenbanken.' 'en-US' = 'Prefix for all databases created by the SharePoint farm.' } } } } } ``` Notes: - `Value` wins over `DefaultValue`. - `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. - `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_-]*$'`. 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 = @{ Provider = 'KeePass' Vault = 'BGW' Name = 'SharePoint/FarmPassphrase' } } SetupCredential = @{ Type = 'credential' Required = $true Sensitive = $true Value = @{ Provider = 'KeePass' Vault = 'BGW' Name = 'SharePoint/SetupAccount' UserName = 'BGW\SVC_SHP_SETUP' } } ``` Secret references are validated by `Resolve-DSCConfigurationData`, but they are resolved by `Resolve-DSCConfigurationSecrets` before the normal data resolve step: ```powershell $withSecrets = Resolve-DSCConfigurationSecrets -ConfigurationData $merged $resolved = Resolve-DSCConfigurationData -ConfigurationData $withSecrets ``` 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 Variables may reference parameters and other variables. Nested variable references are supported. Circular references are rejected. ```powershell @{ Parameters = @{ DatabasePrefix = @{ Type = 'string' DefaultValue = 'SharePoint' } DomainLabel = @{ Type = 'string' Value = 'corp' } Landscape = @{ Type = 'string' Value = 'Test' AllowedValues = @( 'Prod', 'Test' ) } ServiceDatabaseSegment = @{ Type = 'string' DefaultValue = 'Services' } } Variables = @{ StageCode = "[if(equals(parameters('Landscape'), 'Test'), 'TST', 'PRD')]" DatabasePrefix = "[joinNotEmpty('_', parameters('DatabasePrefix'), parameters('DomainLabel'), variables('StageCode'))]" ServiceDbPrefix = "[joinNotEmpty('_', variables('DatabasePrefix'), parameters('ServiceDatabaseSegment'))]" ConfigDbName = "[joinNotEmpty('_', variables('DatabasePrefix'), 'Farm_Config')]" } } ``` Example output: ```text StageCode : TST DatabasePrefix : SharePoint_corp_TST ServiceDbPrefix : SharePoint_corp_TST_Services ConfigDbName : SharePoint_corp_TST_Farm_Config ``` ## Functions ### References ```powershell "[parameters('DatabasePrefix')]" "[variables('ServiceDbPrefix')]" ``` `parameters(name)` returns the effective parameter value. `Value` is used before `DefaultValue`. `variables(name)` resolves another variable. Variables may reference other variables. ### String Composition ```powershell "[concat('SharePoint', '_', 'Services')]" # SharePoint_Services ``` ```powershell "[format('{0}_{1}_{2}', parameters('DatabasePrefix'), parameters('DomainLabel'), parameters('Landscape'))]" # SharePoint_corp_Test ``` ```powershell "[joinNotEmpty('_', parameters('DatabasePrefix'), parameters('DomainLabel'), '', 'Services')]" # SharePoint_corp_Services ``` ```powershell "[defaultIfEmpty(parameters('DatabasePrefix'), 'SharePoint')]" # SharePoint, when DatabasePrefix is empty ``` ```powershell "[coalesce(parameters('CustomPrefix'), parameters('DatabasePrefix'), 'SharePoint')]" # First non-empty value ``` ### Conditions And Boolean Logic ```powershell "[if(equals(parameters('Landscape'), 'Test'), 'TST', 'PRD')]" # TST ``` ```powershell "[equals(parameters('Landscape'), 'Test')]" "[notEquals(parameters('Landscape'), 'Prod')]" "[and(equals(parameters('Landscape'), 'Test'), not(empty(parameters('DatabasePrefix'))))]" "[or(equals(parameters('Landscape'), 'Prod'), equals(parameters('Landscape'), 'Test'))]" "[not(empty(parameters('DatabasePrefix')))]" ``` ### Case And Text ```powershell "[toLower('Contoso-CORP')]" # contoso-corp ``` ```powershell "[toUpper('contoso-corp')]" # CONTOSO-CORP ``` ```powershell "[trim(' SharePoint ')]" "[trimStart(' SharePoint')]" "[trimEnd('SharePoint ')]" ``` ```powershell "[replace('Contoso-CORP', '-', '_')]" # Contoso_CORP ``` ```powershell "[substring('SharePoint', 5, 5)]" # Point ``` ```powershell "[indexOf('CON', 1)]" # G ``` `firstIndexOf` and `lastIndexOf` return the first or last function argument: ```powershell "[firstIndexOf('a', 'b', 'c')]" # a "[lastIndexOf('a', 'b', 'c')]" # c ``` ### Name Cleanup ```powershell "[sanitizeName(' SharePoint corp/Test DB ')]" # SharePoint_corp_Test_DB ``` ```powershell "[sanitizeName(' SharePoint corp/Test DB ', '-')]" # SharePoint-corp-Test-DB ``` ```powershell "[normalizeSeparator('__SharePoint___corp_Test__', '_')]" # SharePoint_corp_Test ``` ```powershell "[prefixIfNotEmpty('corp', 'Contoso-')]" # Contoso-corp ``` ```powershell "[suffixIfNotEmpty('SharePoint', '_DB')]" # SharePoint_DB ``` ### Collections ```powershell "[split(parameters('DomainFQDN'), '.')]" # @('contoso', 'com') ``` ```powershell "[join(split(parameters('DomainFQDN'), '.'), '_')]" # contoso_com ``` ```powershell "[first(split(parameters('DomainFQDN'), '.'))]" # contoso ``` ```powershell "[last(split(parameters('DomainFQDN'), '.'))]" # de ``` ```powershell "[take(split(parameters('DomainFQDN'), '.'), 1)]" # @('contoso') ``` ```powershell "[skip(split(parameters('DomainFQDN'), '.'), 1)]" # @('de') ``` ```powershell "[unique(split('SP.SP.SQL', '.'))]" # @('SP', 'SQL') ``` ```powershell "[sort(split('SQL.SP.APP', '.'))]" # @('APP', 'SP', 'SQL') ``` ### Inspection ```powershell "[contains(parameters('DomainFQDN'), 'online')]" # True ``` ```powershell "[contains(split(parameters('DomainFQDN'), '.'), 'de')]" # True ``` ```powershell "[startsWith(parameters('DomainFQDN'), 'contoso')]" # True ``` ```powershell "[endsWith(parameters('DomainFQDN'), 'de')]" # True ``` ```powershell "[length(split(parameters('DomainFQDN'), '.'))]" # 2 ``` ```powershell "[empty(parameters('OptionalValue'))]" # True, when OptionalValue is empty ``` ### Padding ```powershell "[padLeft('1', 2, '0')]" # 01 ``` ```powershell "[padRight('SP', 4, '0')]" # SP00 ``` ## Full Function List - `parameters(name)` - `variables(name)` - `concat(value1, value2, ...)` - `format(formatString, value1, value2, ...)` - `coalesce(value1, value2, ...)` - `defaultIfEmpty(value, defaultValue)` - `if(condition, trueValue, falseValue)` - `equals(left, right)` - `notEquals(left, right)` - `and(value1, value2, ...)` - `or(value1, value2, ...)` - `not(value)` - `toLower(value)` - `toUpper(value)` - `firstIndexOf(value1, value2, ...)` - `lastIndexOf(value1, value2, ...)` - `indexOf(value, index)` - `substring(value, startIndex)` - `substring(value, startIndex, length)` - `replace(value, oldValue, newValue)` - `sanitizeName(value)` - `sanitizeName(value, separator)` - `normalizeSeparator(value, separator)` - `prefixIfNotEmpty(value, prefix)` - `suffixIfNotEmpty(value, suffix)` - `contains(value, search)` - `startsWith(value, search)` - `endsWith(value, search)` - `split(value, separator)` - `join(array, separator)` - `joinNotEmpty(separator, value1, value2, ...)` - `take(array, count)` - `skip(array, count)` - `first(array)` - `last(array)` - `unique(array)` - `sort(array)` - `trim(value)` - `trimStart(value)` - `trimEnd(value)` - `padLeft(value, totalWidth)` - `padLeft(value, totalWidth, paddingCharacter)` - `padRight(value, totalWidth)` - `padRight(value, totalWidth, paddingCharacter)` - `length(value)` - `empty(value)` ## Validation Run the tests: ```powershell Invoke-Pester -Script '.\PowerShell\Resolve-DSCConfigurationData\.tests\Resolve-DSCConfigurationData.Tests.ps1' ```