在DSC中使用文件提供程序 - 确保Destination仅包含Source中的文件

时间:2014-04-20 00:44:04

标签: powershell dsc

我创建了一个DSC资源来复制某个源的Modules目录。我正在测试它在我的环境中进行更广泛的部署。资源确实很好,确保所有文件都存在,并且它们与源内容相匹配,到目前为止一直很好......

问题在于此;我想确保如果目标或目标中有任何其他文件,则删除它们的文件夹。

这是我的代码:

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
        }
    }
}

第一次运行配置后,我一直在目标目录中创建一个名为Deleteme.flag的文件进行测试。到目前为止,我还没有幸运地将其删除。

我尝试添加额外的文件提供程序要求,以便在运行之前删除目录:

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

不幸的是,这失败并出现以下错误:

  

关键属性组合   'C:\ users \ Jason \ Documents \ WindowsPowerShell \ Modules'是重复的   节点'Localhost'中资源'File'的密钥'DestinationPath'。请   确保关键属性对于节点中的每个资源都是唯一的。

无论如何,我想用文件资源来做,但很明显,使用脚本提供程序或其他一些自定义资源很容易。在此先感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

我是DSC新手。花了周日下午最好的部分来查看资源并试图弄清楚如何解决这个问题。所以,我真诚地感谢你。查看DSC很有意思。

我认为,这可行:

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
        }
    }
}

<强>参考文献:

答案 1 :(得分:0)

您可以先复制文件,然后删除不必要的文件:

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'
    }
}

这样,如果有任何目录树更改,则在复制所需文件之前不必删除所有文件。只有必须添加,修改或删除的文件才会受到影响。