2014-04-28 15 views
23

Mam problem z uzyskaniem skryptu konfiguracji stanu pożądanego programu PowerShell do skonfigurowania aplikacji wewnętrznej. Przyczyną problemu jest to, że nie mogę przekazać danych konfiguracyjnych do źródła ScriptResource (przynajmniej nie tak, jak próbuję to zrobić).PowerShell DSC - jak przekazać parametry konfiguracyjne do ScriptResources?

Mój skrypt powinien utworzyć folder config dla naszej aplikacji w-domu, a następnie napisać kilka ustawień do pliku:

configuration MyApp { 
    param (
     [string[]] $ComputerName = $env:ComputerName 
    ) 
    node $ComputerName { 

     File ConfigurationFolder { 
      Type = "Directory" 
      DestinationPath = $Node.ConfigFolder 
      Ensure = "Present" 
     } 

     Script ConfigurationFile { 
      SetScript = { 
       write-verbose "running ConfigurationFile.SetScript"; 
       write-verbose "folder = $($Node.ConfigFolder)"; 
       write-verbose "filename = $($Node.ConfigFile)"; 
       [System.IO.File]::WriteAllText($Node.ConfigFile, "enabled=" + $Node.Enabled); 
      } 
      TestScript = { 
       write-verbose "running ConfigurationFile.TestScript"; 
       write-verbose "folder = $($Node.ConfigFolder)"; 
       write-verbose "filename = $($Node.ConfigFile)"; 
       return (Test-Path $Node.ConfigFile); 
      } 
      GetScript = { @{Configured = (Test-Path $Node.ConfigFile)} }   
      DependsOn = "[File]ConfigurationFolder" 
     } 

    } 
} 

Dla porównania, moje dane konfiguracja wygląda następująco:

$config = @{ 
    AllNodes = @(
     @{ 
      NodeName = "*" 
      ConfigFolder = "C:\myapp\config" 
      ConfigFile = "C:\myapp\config\config.txt" 
     } 
     @{ 
      NodeName = "ServerA" 
      Enabled = "true" 
     } 
     @{ 
      NodeName = "ServerB" 
      Enabled = "false" 
     } 
    ) 
} 

A ja stosowania DSC z następujących czynności:

$mof = MyApp -ConfigurationData $config; 
Start-DscConfiguration MyApp –Wait –Verbose; 

Kiedy stosuje się ta konfiguracja szczęśliwie tworzy folder, ale nie robi nic z plikiem konfiguracyjnym. Patrząc na wynik poniżej, jest oczywiste, że dzieje się tak dlatego, że zmienna $ Node ma wartość null w zakresie pliku ConfigurationFile/TestScript, ale nie mam pojęcia, jak ją powiązać z poziomu tego bloku.

LCM: [ Start Resource ] [[Script]ConfigurationFile] 
LCM: [ Start Test  ] [[Script]ConfigurationFile] 
          [[Script]ConfigurationFile] running ConfigurationFile.TestScript 
          [[Script]ConfigurationFile] node is null = True 
          [[Script]ConfigurationFile] folder = 
          [[Script]ConfigurationFile] filename = 
LCM: [ End Test  ] [[Script]ConfigurationFile] in 0.4850 seconds. 

Mam wypalane cały dzień szukają w internecie dla tego konkretnego problemu, ale wszystkie przykłady zmiennych, parametrów i danych konfiguracyjnych cały plik i wykorzystanie zasobów rejestru lub innych zasobów niż scenariusz, który ja już działa w bloku "ConfigurationFolder" w moim skrypcie. Problemem, na którym utknąłem, jest odwoływanie się do danych konfiguracyjnych z zasobu skryptu, takiego jak mój "plik konfiguracyjny".

Narysowałem kompletną pustkę, więc każda pomoc będzie bardzo ceniona. Jeśli wszystko inne zawiedzie, będę musiał utworzyć osobny skrypt "konfiguracyjny" na serwer i zakodować wartości, których naprawdę nie chcę robić, jeśli to w ogóle możliwe.

Cheers,

Mike

Odpowiedz

6

ConfigurationData istnieje tylko w czasie MF pliki są kompilowane, a nie w czasie wykonywania, gdy silnik DSC stosuje skrypty. Atrybuty SetScript, GetScript i TestScript zasobu skryptu są w rzeczywistości ciągami, a nie blokami skryptów.

Możliwe jest wygenerowanie tych ciągów skryptów (z wszystkimi wymaganymi danymi z już rozwiniętych danych konfiguracyjnych), ale należy zachować ostrożność, aby poprawnie używać ucieczek, wyrażeń podrzędnych i cudzysłowów.

napisałem krótki przykład tego Powyżej na oryginalnym wątku TechNet w http://social.technet.microsoft.com/Forums/en-US/2eb97d67-f1fb-4857-8840-de9c4cb9cae0/dsc-configuration-data-for-script-resources?forum=winserverpowershell

10

oparciu o odpowiedź Dawida, pisałem funkcję użytkową, która przekształca mój blok skryptu do łańcucha, a następnie wykonuje się bardzo naiwne szukanie i zastąp, aby rozwinąć odniesienia do danych konfiguracyjnych w następujący sposób.

function Format-DscScriptBlock() 
{ 
    param(
     [parameter(Mandatory=$true)] 
     [System.Collections.Hashtable] $node, 
     [parameter(Mandatory=$true)] 
     [System.Management.Automation.ScriptBlock] $scriptBlock 
    ) 
    $result = $scriptBlock.ToString(); 
    foreach($key in $node.Keys) 
    { 
     $result = $result.Replace("`$Node.$key", $node[$key]); 
    } 
    return $result; 
} 

My SetScript wówczas postać:

SetScript = Format-DscScriptBlock -Node $Node -ScriptBlock { 
       write-verbose "running ConfigurationFile.SetScript"; 
       write-verbose "folder = $Node.ConfigFolder"; 
       write-verbose "filename = $Node.ConfigFile)"; 
       [System.IO.File]::WriteAllText("$Node.ConfigFile", "enabled=" + $Node.Enabled); 
      } 

Trzeba pamiętać o cudzysłowach i ucieka w danych konfiguracyjnych ponieważ Format-DscScriptBlock wykonuje tylko dosłowne zmiany, ale to było wystarczająco dobre dla moich celów.

6

Bardzo eleganckim sposobem rozwiązania tego problemu jest praca z regularnymi symbolami zastępczymi {0}. Poprzez zastosowanie operatora -f można zastąpić symbole zastępcze rzeczywistymi wartościami.

Jedyną wadą tej metody jest to, że nie można używać nawiasów klamrowych {} w przypadku obiektów innych niż symbole zastępcze (to znaczy w przypadku hashtable lub pętli for), ponieważ operator -f wymaga, aby nawiasy klamrowe zawierały liczbę całkowitą.

Kod wówczas wygląda następująco:

 SetScript = ({ 
      Set-ItemProperty "IIS:\AppPools\{0}" "managedRuntimeVersion" "v4.0" 
      Set-ItemProperty "IIS:\AppPools\{0}" "managedPipelineMode" 1 # 0 = Integrated, 1 = Classic 
     } -f @($ApplicationPoolName)) 

również dobrym sposobem, aby dowiedzieć się, czy robisz to dobrze jest po prostu oglądanie wygenerowany mof pliku z edytora tekstu; jeśli spojrzysz na wygenerowanych członków TestScript/GetScript/SetScript, zobaczysz, że fragment kodu naprawdę jest łańcuchem znaków. Wartości zastępcze $ powinny już zostać tam zastąpione.

+3

Faktycznie, można użyć nawiasów klamrowych, po prostu trzeba je dwukrotnie (tak '{' staje '{{' i '}' staje się '}}'). – BartekB

27

Zmień to: $Node.ConfigFolder na $using:Node.ConfigFolder.

Jeśli masz zmienną o nazwie $Foo i chcesz go być przekazane do zasobu skrypt DSC, a następnie użyć $using:Foo

+2

, ale ** punktem ** jest umieszczenie go w $() jak: '$ ($ za pomocą: Node.ConfigFolder)' –

+4

To powinno być poprawną odpowiedzią '$ using' jest dostarczona, aby rozwiązać ten problem dla ciebie, nie trzeba wygenerować ciągi samodzielnie ... Zobacz https://msdn.microsoft.com/en-us/powershell/dsc/scriptResource na przykład. –

Powiązane problemy