I’ve been trying to test and evaluate different methods of applying multiple configurations to a node, then audit them long term. I’m aware of different options including partial configurations, dot-sourcing, and composite configurations. I created 2 unique dsc configurations for a node, one installed sql, one installed the docker service, and applied them successfully. Perhaps not real world realistic, but just a test of dot-sourcing. I then wanted to audit the node for both groups of changes. I found that test-dscconfiguration only reads one .mof, the current.mof on the node (I know about -referenceconfiguration, but getting an audit of multiple applied configs would still require multiple passes). I wanted to both perform multiple, separate configurations, without having to combine everything into one large, monolithic configuration script, and also get be able to run one test-dscconfiguration command and return one audit result, without having to combine multiple test-dscconfiguration commands using -referenceconfiguration. I was unable to get partial-configurations to work, so I turned to dot-sourcing the separate dsc scripts within one, and removing the configuration and node separations in the lower level scripts. I found that the separate scripts worked fine standalone, but the sql script throws an error when dot-sourced.
The docker service install script works fine, as standalone and in the dot-sourced script. The sql install script works fine standalone, but throws an error when dot-sourced.
DSC script containing 2 dot-sourced scripts
#DSC_install_docker-sql-test.ps1 $Nodelist = get-content dsc_install_docker_and_SQL-nodelist.txt $Config = 'DSC_install_docker_and_SQL_test' $dockersqlnodeconfigdata = @{ AllNodes = @( @{ NodeName = '*' PSDscAllowPlainTextPassword = $true PSDscAllowDomainUser = $true DomainAdminCredential = (Get-Credential -message "Enter a Domain Admin ID for the Server Node") } ) } ForEach ($Node in $Nodelist) { Configuration DSC_install_docker_and_SQL_test { Import-DscResource –ModuleName 'PSDesiredStateConfiguration' node $node { . ./dsc_install_docker-dotsourced.ps1 . ./dscconfig_sqlnodes_serial-dotsourced.ps1 } } write-output ".mof file should be in: $config" pause DSC_install_docker_and_SQL_test -configurationdata $dockersqlnodeconfigdata -outputpath "c:\PROGRAM FILES\WindowsPowerShell\DscService\Configuration\$Config" write-host "if you don't see the name of a .mof file here, one was not created" pause #good place to pause to verify $node.mof and/or $node.meta.mof file creation. } foreach ($node in $nodelist) { $cimsession = '' $cimsession = new-cimsession -credential $DomainAdminCredential -computername $Node Start-DSCConfiguration -cimsession $cimsession -Path "c:\PROGRAM FILES\WindowsPowerShell\DscService\Configuration\$Config" -wait -Verbose -force $sleepseconds = 20 write-output "Sleeping $sleepseconds seconds before checking DSC Configuration Status...Please wait." start-sleep -seconds $sleepseconds Get-DscConfigurationstatus -CimSession $cimsession | select pscomputername,startdate,type,status,mode,numberofresources | format-table -autosize (test-dscconfiguration -detailed -cimsession $cimsession).resourcesindesiredstate | select pscomputername,ResourceID,InDesiredState | format-table -autosize } DSC sql install script standalone #DSCconfig_SQLNodes_serial.ps1 $Nodelist = get-content dscconfig_sqlnodelist.txt $Config = 'ConfigDSC_SQLNodes_Serial' $mofconfigpath = "c:\PROGRAM FILES\WindowsPowerShell\DscService\Configuration\$Config" $DomainAdminCredential = Get-Credential -username $env:userdomain\$env:username -message "Domain Administrator UserID and Password for module source, module destination, SQL source, and SQL install" $SourceCredential = $DomainAdminCredential $Module_Source = "\\se123456\dsc\module_storage" $Module_Destination = "c$\program files\windowspowershell\modules" get-cimsession | remove-cimsession $cimsessions = new-cimsession -ComputerName $Nodelist -Credential $SQLInstallCredential get-smbmapping | Remove-SmbMapping -Force $source_userid = $Sourcecredential.username $source_password = $Sourcecredential.getnetworkcredential().password new-smbmapping -remotepath $module_source -username $source_userid -password $source_password $source_userid = "" $source_password = "" foreach ($Node in $Nodelist) { $DestinationCredential = $DomainAdminCredential $destination_userid = $destinationCredential.UserName $destination_password = $destinationCredential.getnetworkcredential().password new-smbmapping -remotepath "\\$Node\$module_destination" -username $destination_userid -password $destination_password $destination_userid = "" $destination_password = "" if (-not (test-path "\\$Node\$module_destination\xSQLServer\7.1.0.0\")) { copy-item -path "$module_source\xSQLServer\7.1.0.0\" -destination "\\$Node\$module_destination\xSQLServer\" -Recurse -Force } if (-not (test-path "\\$Node\$module_destination\xPSDesiredStateConfiguration\")) { copy-item -path "$module_source\xPSDesiredStateConfiguration\" -destination "\\$Node\$module_destination\" -Recurse -Force } get-childitem "\\$Node\$module_destination\xSQLServer" | select fullname get-childitem "\\$Node\$module_destination\xPSDesiredStateConfiguration" | select fullname } $sqlnodeconfigdata = @{ AllNodes = @( @{ NodeName = '*' PSDscAllowPlainTextPassword = $true PSDscAllowDomainUser = $true SQLInstallCredential = $DomainAdminCredential SQLAdminCredential = (Get-Credential -username SA -message "Enter SA credential") SourceCredential = $DomainAdminCredential } ) } ForEach ($Node in $Nodelist) { $sqlnodeConfigData.AllNodes += @{ NodeName = $Node } } configuration ConfigDSC_SQLNodes_Serial { Import-DscResource -ModuleName PSDesiredStateConfiguration Import-DscResource -Name "xSQLServersetup" -ModuleName "xSQLServer" -ModuleVersion "7.1.0.0" Node $allnodes.nodename { WindowsFeature DSC-Service { Name = "DSC-Service" Ensure = "Present" } WindowsFeature RSAT { Name = "RSAT" Ensure = "Present" } WindowsFeature NET-Framework-Core { Name = "NET-Framework-Core" Ensure = "Present" } #======================================================================================== File xPSDesiredStateConfiguration_Copy { Ensure = "Present" Type = "Directory" DestinationPath = "C:\Program Files\WindowsPowerShell\Modules\xPSDesiredStateConfiguration" } File xSQLServer_Add { Ensure = "Present" Type = "Directory" DestinationPath = "C:\Program Files\WindowsPowerShell\Modules\xSQLServer\7.1.0.0" } #==================================================================== xSQLServerSetup 'InstallNamedInstance_IN01' { DependsOn = "[File]xSQLServer_Add" InstanceName = 'IN01' Features = 'SQLENGINE,CONN,BC' SQLSYSADMINACCOUNTS = "DEVDOMAIN\Server_Local_Admins", "DEVDOMAIN\MSSQL_Admins" SetupCredential = $Node.SQLInstallCredential SECURITYMODE = "SQL" InstallSharedDir = 'F:\Program Files\Microsoft SQL Server' InstallSharedWOWDir = 'F:\Program Files (x86)\Microsoft SQL Server' InstanceDir = 'F:\Program Files\Microsoft SQL Server' InstallSQLDataDir = 'F:\Program Files\Microsoft SQL Server\MSSQL13.INST2016\MSSQL\Data' SourceCredential = $Node.SourceCredential SourcePath = "\\se123456\dsc\Sql2016x64Ent" UpdateEnabled = 'False' ForceReboot = $false BrowserSvcStartupType = 'Automatic' SAPwd = $Node.SQLAdminCredential } } } #================ Create .mof file for server/node ============================================ $sqlnodeconfigdata.allnodes pause ConfigDSC_SQLNodes_Serial -configurationdata $sqlnodeconfigdata -outputpath $mofconfigpath foreach($Node in $Nodelist) { $cimsession = new-cimsession -ComputerName $Node -Credential $SQLInstallCredential Start-DSCConfiguration -cimsession $cimsession -Path $mofconfigpath -wait -Verbose -force } write-output "Sleeping for 10 seconds before checking DSC Configuration Status for $node..." start-sleep -seconds 10 foreach($Node in $Nodelist) { Get-DscConfigurationstatus -CimSession $cimsession | select pscomputername,startdate,type,status,mode,numberofresources | format-table -autosize (test-dscconfiguration -detailed -computername $node).resourcesindesiredstate | select pscomputername,ResourceID,InDesiredState | format-table -autosize (test-dscconfiguration -detailed -computername $node).resourcesnotindesiredstate | select pscomputername,ResourceID,InDesiredState | format-table -autosize } DSC sql install script when dot-sourced in combined dsc script #DSCconfig_SQLNodes_serial-dotsourced.ps1 $Nodelist = get-content dscconfig_sqlnodelist.txt $Config = 'ConfigDSC_SQLNodes_Serial' $mofconfigpath = "c:\PROGRAM FILES\WindowsPowerShell\DscService\Configuration\$Config" $DomainAdminCredential = Get-Credential -username $env:userdomain\$env:username -message "Domain Administrator UserID and Password for module source, module destination, SQL source, and SQL install" $SourceCredential = $DomainAdminCredential $Module_Source = "\\se123456\dsc\module_storage" $Module_Destination = "c$\program files\windowspowershell\modules" get-cimsession | remove-cimsession $cimsessions = new-cimsession -ComputerName $Nodelist -Credential $SQLInstallCredential get-smbmapping | Remove-SmbMapping -Force $source_userid = $Sourcecredential.username $source_password = $Sourcecredential.getnetworkcredential().password new-smbmapping -remotepath $module_source -username $source_userid -password $source_password $source_userid = "" $source_password = "" foreach ($Node in $Nodelist) { $DestinationCredential = $DomainAdminCredential $destination_userid = $destinationCredential.UserName $destination_password = $destinationCredential.getnetworkcredential().password new-smbmapping -remotepath "\\$Node\$module_destination" -username $destination_userid -password $destination_password $destination_userid = "" $destination_password = "" if (-not (test-path "\\$Node\$module_destination\xSQLServer\7.1.0.0\")) { copy-item -path "$module_source\xSQLServer\7.1.0.0\" -destination "\\$Node\$module_destination\xSQLServer\" -Recurse -Force } if (-not (test-path "\\$Node\$module_destination\xPSDesiredStateConfiguration\")) { copy-item -path "$module_source\xPSDesiredStateConfiguration\" -destination "\\$Node\$module_destination\" -Recurse -Force } get-childitem "\\$Node\$module_destination\xSQLServer" | select fullname get-childitem "\\$Node\$module_destination\xPSDesiredStateConfiguration" | select fullname } $sqlnodeconfigdata = @{ AllNodes = @( @{ NodeName = '*' PSDscAllowPlainTextPassword = $true PSDscAllowDomainUser = $true SQLInstallCredential = $DomainAdminCredential SQLAdminCredential = (Get-Credential -username SA -message "Enter SA credential") SourceCredential = $DomainAdminCredential } ) } ForEach ($Node in $Nodelist) { $sqlnodeConfigData.AllNodes += @{ NodeName = $Node } } Import-DscResource -ModuleName PSDesiredStateConfiguration Import-DscResource -Name "xSQLServersetup" -ModuleName "xSQLServer" -ModuleVersion "7.1.0.0" WindowsFeature DSC-Service { Name = "DSC-Service" Ensure = "Present" } WindowsFeature RSAT { Name = "RSAT" Ensure = "Present" } WindowsFeature NET-Framework-Core { Name = "NET-Framework-Core" Ensure = "Present" } #======================================================================================== File xPSDesiredStateConfiguration_Copy { Ensure = "Present" Type = "Directory" DestinationPath = "C:\Program Files\WindowsPowerShell\Modules\xPSDesiredStateConfiguration" } File xSQLServer_Add { Ensure = "Present" Type = "Directory" DestinationPath = "C:\Program Files\WindowsPowerShell\Modules\xSQLServer\7.1.0.0" } #==================================================================== xSQLServerSetup 'InstallNamedInstance_IN01' { DependsOn = "[File]xSQLServer_Add" InstanceName = 'IN01' Features = 'SQLENGINE,CONN,BC' SQLSYSADMINACCOUNTS = "DEVDOMAIN\Server_Local_Admins", "DEVDOMAIN\MSSQL_Admins" SetupCredential = $Node.SQLInstallCredential SECURITYMODE = "SQL" InstallSharedDir = 'F:\Program Files\Microsoft SQL Server' InstallSharedWOWDir = 'F:\Program Files (x86)\Microsoft SQL Server' InstanceDir = 'F:\Program Files\Microsoft SQL Server' InstallSQLDataDir = 'F:\Program Files\Microsoft SQL Server\MSSQL13.INST2016\MSSQL\Data' SourceCredential = $Node.SourceCredential SourcePath = "\\se123456\dsc\Sql2016x64Ent" UpdateEnabled = 'False' ForceReboot = $false BrowserSvcStartupType = 'Automatic' SAPwd = $Node.SQLAdminCredential }
Error when running dsc sql script as dot-sourced
PS C:\Program Files\WindowsPowerShell\DscService\Configuration> .\dsc_install_docker-sql-test.ps1
PSDesiredStateConfiguration\node : The term ‘xSQLServer\xSQLServerSetup’ is not recognized as the name of a cmdlet,
function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the
path is correct and try again.
At C:\Program Files\WindowsPowerShell\DscService\Configuration\dsc_install_docker-sql-test.ps1:38 char:3
-
node $node
-
~~~~
- CategoryInfo : ObjectNotFound: (xSQLServer\xSQLServerSetup:String) [PSDesiredStateConfiguration\node],
ParentContainsErrorRecordException - FullyQualifiedErrorId : CommandNotFoundException,PSDesiredStateConfiguration\node
- CategoryInfo : ObjectNotFound: (xSQLServer\xSQLServerSetup:String) [PSDesiredStateConfiguration\node],
Compilation errors occurred while processing configuration ‘DSC_install_docker_and_SQL_test’. Please review the errors
reported in error stream and modify your configuration code appropriately.
At
C:\Windows\system32\WindowsPowerShell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:3917
char:5
-
throw $ErrorRecord
-
~~~~~~~~~~~~~~~~~~
- CategoryInfo : InvalidOperation: (DSC_install_docker_and_SQL_test:String) , InvalidOperationException
- FullyQualifiedErrorId : FailToProcessConfiguration
PS C:\Program Files\WindowsPowerShell\DscService\Configuration>
Does anyone have any advice on what the cause of the error could be, and how to resolve it?