Using the File provider in DSC - Ensure Destination only contains files from Source

孤人 提交于 2019-12-07 06:30:30

问题


I've created a DSC resource to copy a Modules directory from a certain source. I'm testing it for a broader deployment in my environment. The resource does a great job ensuring all the files are there and that they match the source content, so far so good...

The problem is this; I want to ensure that if there are any additional files in the target, or destination, a folder that they get removed.

Here's my code:

Configuration TestRun
{
  Param 
    (
      $ComputerName = 'Localhost'
    )
  Node $ComputerName
    {
      File LoadModules
        {
          Ensure = 'Present'
          Type = 'Directory'
          Force = $true
          Recurse = $true
          SourcePath = "C:\git\Modules"
          DestinationPath = 'C:\users\Jason\Documents\WindowsPowerShell\Modules'
          Checksum = "SHA-256"
          MatchSource = $true
        }
    }
}

I've been testing by creating a file in the destination directory after running the config the first time called Deleteme.flag. So far I haven't had any luck getting it actually to be deleted.

I tried adding an additional File provider requirement to remove the directory before it runs:

 File RemoveModules
    {
      Ensure = 'absent'
      Type = 'Directory'
      Force = $true
      Recurse = $true
      DestinationPath = 'C:\users\Jason\Documents\WindowsPowerShell\Modules'
    }

Unfortunately, this fails with the following error:

The key properties combination 'C:\users\Jason\Documents\WindowsPowerShell\Modules' is duplicated for keys 'DestinationPath' of resource 'File' in node 'Localhost'. Please make sure key properties are unique for each resource in a node.

Anyway, I'd like to do it with the file resource, but obviously, it would be easy to do it with the script provider or some other custom resource. Thanks in advance for all your help!


回答1:


I am new to DSC. Spent the best part of Sunday afternoon looking at the resources and trying to figure out how to solve this. So, I sincerely thank you for that. It was fun looking up on DSC.

I think, this could work:

Configuration TestRun
{
  Param 
    (
      $ComputerName = 'Localhost'
    )
    Node $ComputerName
    {
        Script RemoveModules { 
            GetScript = {#needs to return hashtable.}
            SetScript = { 
                $ump = "$HOME" + "\Documents\WindowsPowerShell\Modules\"
                Remove-Item -Path $ump -Recurse -Force
            }
            TestScript = { 
                $ump = "$HOME" + "\Documents\WindowsPowerShell\Modules\"
                $mp = "C:\git\Modules"
                if((Compare-Object $(gci $mp) $(gci $ump))){
                    $false #at least one difference exists, SetScript will be called.
                }else{
                    $true #nothing is different
                }

            }
        }
        File LoadModules
        {
            Ensure = 'Present'
            Type = 'Directory'
            Force = $true
            Recurse = $true
            SourcePath = "C:\git\Modules"
            DestinationPath = 'C:\users\Jason\Documents\WindowsPowerShell\Modules'
            DependsOn = "[Script]RemoveModules"
            Checksum = "SHA-256"
            MatchSource = $true
        }
    }
}

References:

  • DSC Script Resource
  • DSC File Resource
  • PowerShellMagazine - Tag DSC



回答2:


You can first copy the files and then delete the unnecessary ones:

Configuration DirectoryCopy
{
    param
    (
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String] $SourcePath,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String] $DestinationPath
    )

    File CopyFiles
    {
        SourcePath      = $SourcePath
        DestinationPath = $DestinationPath
        Type            = 'Directory'
        Recurse         = $true
        Checksum        = 'SHA-256'  # Overwrite modified files
        Force           = $true
    }

    Script DeleteAdditionalDestinationFiles
    {
        TestScript =
        {
            $currentFiles = Get-ChildItem $using:DestinationPath -Recurse
            $desiredFiles = Get-ChildItem $using:SourcePath -Recurse

            $hasAdditionalFiles = [bool](Compare-Object -ReferenceObject $currentFiles -DifferenceObject $desiredFiles)

            return !$hasAdditionalFiles
        }
        SetScript =
        {
            $currentFiles = Get-ChildItem $using:DestinationPath -Recurse
            $desiredFiles = Get-ChildItem $using:SourcePath -Recurse

            $additionalFiles = Compare-Object -ReferenceObject $currentFiles -DifferenceObject $desiredFiles | Select-Object -ExpandProperty InputObject

            # First remove the directories and all its descendants.
            $additionalFiles | Where-Object { ($_.Attributes -band [IO.FileAttributes]::Directory) -eq [IO.FileAttributes]::Directory } | Remove-Item -Recurse -Verbose

            # Remove the remaining files that were not in any already removed directory.
            $additionalFiles | Where-Object { Test-Path -Path $_.FullName } | Remove-Item -Verbose
        }
        GetScript = {
            $currentFiles = Get-ChildItem $using:DestinationPath -Recurse

            return @{
                Result     = $currentFiles
                TestScript = $TestScript
                SetScript  = $SetScript
                GetScript  = $GetScript
            }
        }

        DependsOn = '[File]CopyFiles'
    }
}

In this way, if there are any directory tree change, it will not be necessary to delete all files before copying the desired ones. Only files that must be added, modified or removed will be affected.



来源:https://stackoverflow.com/questions/23177212/using-the-file-provider-in-dsc-ensure-destination-only-contains-files-from-sou

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!