Jason
Jason

Reputation: 78

PowerShell DSC resouce not finding Configuration keyword

I am working on getting a DSC configuration setup for our development machines. What I've run into is either an error with how I'm doing composite resources or something I can't see.

I can run the DevMachineConfig.ps1 with no issues, but when I go to create the MOF files using DeveloperMachine -ConfigurationData $ConfigurationData, I get the following error:

PSDesiredStateConfiguration\Configuration : The argument is null. Provide a valid value for 
the argument, and then try running the command again.
At C:\Program Files\WindowsPowerShell\Modules\DeveloperConfig\DSCResources\CreateDomainController\CreateDomainController.schema.psm1:1 char:1
+ Configuration CreateDomainController
+ ~~~~~~~~~~~~~
+ CategoryInfo          : MetadataError: (:) [Configuration], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ArgumentIsNull,Configuration

I'm just not clear on why the null is happening on the Configuration keyword as that would seem to be a built into DSC.

So my question would be is this an error on my part or DSC's?

Below are the files and relevant information

My layout for the "project":

\DevMachineConfig.ps1
\Modules\DeveloperConfig\DeveloperConfg.psd1
\Modules\DeveloperConfig\DSCResources\GetDscResources\GetDscResources.schema.psm1
\Modules\DeveloperConfig\DSCResources\CreateDomainController\CreateDomainController.schema.psm1

*The Modules folder is junctioned to $env:ProgramFiles\WindowsPowershell\Modules

DevMachineConfig.ps1

$ConfigurationData = @{
AllNodes = @(
    @{ 
        NodeName = "localhost"; 
        DomainName = "dev.loc";
        PSDscAllowPlainTextPassword = $true;            
        DomainUsers = @(
            @{ Name = 'web-app'; DomainAdmin = $False }               
        );
     }
)
}

Configuration DeveloperMachine 
{
   $installPassword = ConvertTo-SecureString "password!!" -AsPlainText -Force
   $credentials = New-Object 
             System.Management.Automation.PSCredential("deltaadmin" $installPassword)

Import-DscResource -ModuleName DeveloperConfig, xSystemSecurity

Node "localhost"
{
    LocalConfigurationManager 
    {
        DebugMode = "All"
        ActionAfterReboot = "ContinueConfiguration"
    }

    GetDscResources DSCResources { }

    CreateDomainController DevDomain {
        DomainName = $Node.DomainName
        DomainUsers = $Node.DomainUsers
        DependsOn = "[SetWindowsFeatures]Features"
    }
}

GetDscResources.schema.psm1

Configuration GetDscResources 
{
    param(
        [string] $WorkingDir = "c:\temp\dsc\", 
        [string] $DownloadUrl = "https://gallery.technet.microsoft.com/scriptcenter/DSC-Resource-Kit-All-c449312d/file/131371/1/DSC%20Resource%20Kit%20Wave%209%2012172014.zip"
    )

    $archivePath = Join-Path $WorkingDir "dsc-wave9.zip"
    $resourcesPath = Join-Path $WorkingDir "All Resources"
    $powerShellModule = Join-Path $env:ProgramFiles "WindowsPowerShell\Modules"

    File DeltaDscFolder {
        Ensure = "Present"        
        Type = "Directory"
        DestinationPath = $WorkingDir
    }

    Script DownloadDscResources 
    {
        TestScript = {
            Write-Verbose -Verbose "Checking to see if the path [$using:WorkingDir] exists"
            Write-Verbose -Verbose "Found the Path: $(Test-Path $using:WorkingDir)"
            return !(Test-Path $using:WorkingDir)
        }
        GetScript = { 
            if((Test-Path $(Join-Path $using:powerShellModule "xActiveDirectory")))
            {
                $result = "DSC Resources have been downloaded."
            } else {
                $result = "DSC Resources have not been downloaded."
            }

            return @{ 
                Result = $result
                GetScript = $GetScript
                SetScript = $SetScript
                TestScript = $TestScript
            }
        }
        SetScript = {
            Write-Verbose -Verbose "Downloading the wave9 resources from $using:DownloadUrl to $using:archivePath"
            (New-Object System.Net.WebClient).DownloadFile($using:DownloadUrl, $using:archivePath)
            Write-Verbose -Verbose "Download complete"
        }
        DependsOn = "[File]DeltaDscFolder"
    }

    Archive DscResourceWave9 {
        Destination = $WorkingDir
        Path = $archivePath
        Ensure = "Present"
        DependsOn = "[Script]DownloadDscResources"
    }

    File MoveDscTo {
        Ensure = "Present"
        Type = "Directory"
        Recurse = $true
        SourcePath = $resourcesPath
        DestinationPath = $powerShellModule
        DependsOn = "[Archive]DscResourceWave9"
    }
}

CreateDomainController.schema.psm1

Configuration CreateDomainController 
{
    Param(
        [string] $DomainName = "dev.loc",
        [Parameter(Mandatory)]
        [Hashtable[]] $DomainUsers = $null
    )

    Import-Module -Name ActiveDirectory 
    Import-DscResource -ModuleName xActiveDirectory

    $password = ConvertTo-SecureString "password1!!" -AsPlainText -Force
    $credentials = New-Object System.Management.Automation.PSCredential("admin", $password)

        xADDomain DevelopmentDomain
        {
            DomainName = $DomainName
            DomainAdministratorCredential = $credentials
            SafemodeAdministratorPassword = $credentials
        }

        xWaitForADDomain ADForestWait
        {
            DomainName = $DomainName
            DomainUserCredential = $credentials
            RetryCount = 20
            RetryIntervalSec = 30
            DependsOn = "[xADDomain]DevelopmentDomain"
        }

        <#
            Generate the domain users.
        #>

        foreach($domainUser in $DomainUsers) 
        {
            xADUser $domainUser.Name
            {
                DomainName = $DomainName
                DomainAdministratorCredential = $credentials
                UserName = $domainUser.Name
                Password = $credentials
                Ensure = "Present"
                DependsOn = "[xWaitForADDomain]ADForestWait"            
            }

            if($domainUser.DomainAdmin -eq $True)
            {
                Add-ADPrincipalGroupMembership -Identity $adminUser.Name -MemberOf "Domain Admins"               
            }

            if($domainUser.DelegateAccount -eq $True)
            {
                $rootDse = [ADSI]"LDAP://RootDSE"
                $principal = New-Object Security.Principal.NTAccount("DEV\$($domainUser.Name)")   
                DSACLS "$($rootDse.defaultNamingContext)" /G "$($principal):CA;Replicating Directory Changes"
                DSACLS "$($rootDse.configurationNamingContext)" /G "$($principal):CA;Replicating Directory Changes"
            }
        }
}

Upvotes: 1

Views: 662

Answers (1)

briantist
briantist

Reputation: 47862

Param(
    [string] $DomainName = "dev.loc",
    [Parameter(Mandatory)]
    [Hashtable[]] $DomainUsers = $null
)

This is more of a Powershell problem than DSC specifically. You've got a mandatory parameter with a default value. You should choose one or the other.

Mandatory means that it's mandatory for the parameter to be supplied. A default value should really be used with Mandatory=$false because then its behavior makes more sense (use this value if the caller doesn't supply one).

Upvotes: 1

Related Questions