2014-04-28 16 views
23

Sto avendo un sacco di problemi nel cercare di ottenere uno script di configurazione di stato desiderato PowerShell che funzioni per configurare un'applicazione interna. La radice del problema è che non riesco a passare i miei dati di configurazione in una ScriptResource (almeno non nel modo in cui sto provando a farlo).DSC PowerShell - come passare i parametri di configurazione a ScriptResources?

mio script dovrebbe creare una cartella di configurazione per la nostra applicazione in-house, e quindi scrivere alcune impostazioni in un file:

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

    } 
} 

Per riferimento, il mio dati di configurazione si presenta così:

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

E sto applicando DSC con il seguente:

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

Quando applico questa configurazione crea felicemente la cartella, ma non riesce a fare nulla con il file di configurazione. Osservando l'output di seguito, è ovvio che è perché la variabile $ Node è nullo nell'ambito di ConfigurationFile/TestScript, ma non ho idea di come fare riferimento da quel blocco.

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. 

ho bruciato un intero giorno alla ricerca online per questo specifico problema, ma tutti gli esempi di variabili, parametri e dati di configurazione tutto l'uso di file e risorse del Registro di sistema o altre risorse non di script, che ho già funzionante nel blocco "ConfigurationFolder" nel mio script. La cosa su cui sono bloccato è come fare riferimento ai dati di configurazione all'interno di una risorsa Script come il mio "ConfigurationFile".

Ho disegnato uno spazio vuoto in modo tale che qualsiasi aiuto sarebbe molto apprezzato. Se tutto il resto fallisce, potrei dover creare uno script di "configurazione" separato per server e codificare i valori, cosa che in realtà non voglio fare se possibile.

Cheers,

Mike

risposta

6

Dati di configurazione esiste solo al momento i file MOF vengono compilati, non in fase di esecuzione quando il motore DSC applica script. Gli attributi SetScript, GetScript e TestScript della risorsa Script sono in realtà stringhe, non blocchi di script.

È possibile generare quelle stringhe di script (con tutti i dati richiesti dal proprio ConfigurationData già espanso), ma è necessario fare attenzione a utilizzare fughe, sottoespressioni e virgolette correttamente.

ho postato un breve esempio di questo corso sul filo TechNet originale a http://social.technet.microsoft.com/Forums/en-US/2eb97d67-f1fb-4857-8840-de9c4cb9cae0/dsc-configuration-data-for-script-resources?forum=winserverpowershell

10

in base alla risposta di David, ho scritto una funzione di utilità che converte il mio blocco di script in una stringa e poi esegue una ricerca molto ingenuo e sostituire per espandere i riferimenti ai dati di configurazione come segue.

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

mio setScript diventa allora:

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

Bisogna essere consapevoli di citazioni e sfugge vostri dati di configurazione, perché Format-DscScriptBlock esegue solo la sostituzione letterale, ma questo era abbastanza buono per i miei scopi.

6

Un modo abbastanza elegante per risolvere questo problema è lavorare con i segnaposto regolari {0}. Applicando l'operatore -f i segnaposti possono essere sostituiti con i loro valori effettivi.

L'unico inconveniente di questo metodo è che non è possibile utilizzare le parentesi graffe {} per altro che segnaposto (cioè dire una tabella hash o for-loop), perché l'operatore -f richiede le parentesi per contenere un numero intero.

il codice sia quindi in questo modo:

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

Inoltre, un buon modo per scoprire se si sta facendo giusto è semplicemente visualizzando il generati .mof file con un editor di testo; se guardi i membri TestScript/GetScript/SetScript generati, vedrai che il frammento di codice è davvero una stringa. I valori $ placeholder dovrebbero già essere stati sostituiti lì.

+3

In realtà, è possibile utilizzare le parentesi graffe, hai solo bisogno di raddoppiare loro (in modo '{' diventa '{{' e '}' diventa '}}'). – BartekB

27

Modifica: $Node.ConfigFolder a $using:Node.ConfigFolder.

Se si dispone di una variabile chiamata $Foo e si desidera che sia passato a una risorsa di script DSC, quindi utilizzare $using:Foo

+2

ma ** il punto ** è di metterlo in $() come: '$ ($ usando: Node.ConfigFolder)' –

+4

Questa _should_ essere la risposta corretta '$ using' è fornita per risolvere questo problema per te, no è necessario generare le stringhe da soli ... Vedere https://msdn.microsoft.com/en-us/powershell/dsc/scriptResource per un esempio. –