Megosztás a következőn keresztül:


Oktatóanyag: Osztályalapú DSC-erőforrás létrehozása gépkonfigurációhoz

Első lépések egy osztályalapú DSC-erőforrás létrehozásához egy konfigurációs fájl kezeléséhez az Azure Automanage gépkonfigurációs funkciójával. Az oktatóanyag elvégzése egy gépkonfigurációval kompatibilis osztályalapú DSC-erőforrást biztosít a további tanuláshoz és testreszabáshoz használható modulban.

Eben az oktatóanyagban az alábbiakkal fog megismerkedni:

  • DSC-erőforrásmodul létrehozása
  • Osztályalapú DSC-erőforrás hozzáadása
  • DSC-erőforrás tulajdonságainak definiálása
  • A DSC-erőforrás metódusainak implementálása
  • DSC-erőforrás exportálása moduljegyzékben
  • DSC-erőforrás manuális tesztelése

Megjegyzés

Az oktatóanyagban szereplő példakimenet a PowerShell 7.2-nek felel meg windowsos számítógépen. Az oktatóanyag a Windows PowerShell és a PowerShell használatával érvényes Linux vagy macOS rendszerű számítógépen. Csak a kimenet a parancsok Windows-számítógépen való PowerShellben való futtatására vonatkozik.

Előfeltételek

  • PowerShell vagy Windows PowerShell 5.1
  • VS Code a PowerShell-bővítménnyel

1 – DSC-erőforrásmodul létrehozása

A DSC-erőforrásokat egy PowerShell-modulban kell definiálni.

A modulmappa létrehozása

Hozzon létre egy nevű új mappát ExampleResources. Ez a mappa lesz a modul gyökérmappája, és az oktatóanyagban szereplő összes kód.

New-Item -Path './ExampleResources' -ItemType Directory
    Directory: C:\code\dsc

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----            9/8/2022 12:54 PM                ExampleResources

A modul létrehozása a VS Code használatával

Nyissa meg a mappát a ExampleResources VS Code-ban. Nyissa meg az integrált terminált a VS Code-ban. Győződjön meg arról, hogy a terminálon PowerShell vagy Windows PowerShell fut.

Fontos

Az oktatóanyag további részében futtassa a megadott parancsokat az integrált terminálban a modulmappa gyökerében. Ez a VS Code alapértelmezett munkakönyvtára.

A modulfájlok létrehozása

Hozza létre a moduljegyzéket a New-ModuleManifest parancsmaggal. Használja ./ExampleResources.psd1 elérési útként. Adja meg a RootModule ésExampleResources.psm1 a DscResourcesToExport értéket a következőként: Tailspin.

$ModuleSettings = @{
    RootModule           = 'ExampleResources.psm1'
    DscResourcesToExport = 'Tailspin'
}

New-ModuleManifest -Path ./ExampleResources.psd1 @ModuleSettings
Get-Module -ListAvailable -Name ./ExampleResources.psd1 | Format-List
Name              : ExampleResources
Path              : C:\code\dsc\ExampleResources\ExampleResources.psd1
Description       :
ModuleType        : Script
Version           : 0.0.1
PreRelease        :
NestedModules     : {}
ExportedFunctions :
ExportedCmdlets   :
ExportedVariables :
ExportedAliases   :

Hozza létre a gyökérmodulfájlt a következő néven: ExampleResources.psm1.

New-Item -Path ./ExampleResources.psm1
    Directory: C:\code\dsc\ExampleResources

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            9/8/2022  1:57 PM              0 ExampleResources.psm1

Hozzon létre egy nevű Helpers.ps1szkriptfájlt.

New-Item -Path ./Helpers.ps1
    Directory: C:\code\dsc\ExampleResources

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---            9/8/2022  1:58 PM              0 Helpers.ps1

Nyissa meg Helpers.ps1 a VS Code-ban. Adja hozzá a következő sort.

$env:PSModulePath += "$([System.IO.Path]::PathSeparator)$pwd"

Nyissa meg ExampleResources.psm1 a VS Code-ban. A modul most már készen áll egy DSC-erőforrás létrehozására.

2 – Osztályalapú DSC-erőforrás hozzáadása

Osztályalapú DSC-erőforrás definiálásához egy PowerShell-osztályt írunk egy modulfájlba, és hozzáadjuk hozzá a DscResource attribútumot.

Az osztály meghatározása

A fájlban ExampleResources.psm1adja hozzá a következő kódot:

[DscResource()]
class Tailspin {

}

Ez a kód osztályalapú DSC-erőforrásként ad hozzá Tailspin az ExampleResources modulhoz .

Mutasson rá, [DscResource()] és olvassa el a figyelmeztetéseket.

Képernyőkép a DSCResource attribútum figyelmeztetéséről a VS Code-ban.

A DSCResource attribútumra való rámutatás négy figyelmeztetést jelenít meg. 1. A "Tailspin" DSC-erőforrásból hiányzik egy "Set()" metódus, amely "[void]" értéket ad vissza, és nem fogad el paramétereket. 2. A "Tailspin" DSC-erőforrásból hiányzik egy "Get()" metódus, amely "[Tailspin]" értéket ad vissza, és nem fogad el paramétereket. 3. A "Tailspin" DSC-erőforrás nem tartalmaz egy "Test()" metódust, amely "[bool]" értéket ad vissza, és nem fogad el paramétereket. 4. A "Tailspin" DSC-erőforrásnak rendelkeznie kell legalább egy kulcstulajdonsággal (a következő szintaxist használva: "[DscProperty(Key)]".)

Ezek a figyelmeztetések felsorolják az osztály érvényes DSC-erőforrásra vonatkozó követelményeit.

Minimálisan implementálja a szükséges metódusokat

Adja hozzá a Get(), Test()és Set() metódusok minimális implementációját a osztályhoz.

class Tailspin {
    [Tailspin] Get() {
        $CurrentState = [Tailspin]::new()
        return $CurrentState
    }

    [bool] Test() {
        return $true
    }

    [void] Set() {}
}

A hozzáadott metódusok esetén a DscResource attribútum csak arra figyelmeztet, hogy az osztály nem rendelkezik Key tulajdonsággal.

3 – DSC-erőforrás tulajdonságainak meghatározása

A metódusok előtt meg kell határoznia a DSC-erőforrás tulajdonságait. A tulajdonságok határozzák meg a DSC-erőforrás kezelhető beállításait. A metódusokban használják őket.

A TSToy-alkalmazás ismertetése

Mielőtt definiálná a DSC-erőforrás tulajdonságait, meg kell értenie, hogy milyen beállításokat szeretne kezelni.

Ebben az oktatóanyagban egy DSC-erőforrást határozunk meg a fiktív TSToy-alkalmazás beállításainak kezeléséhez a konfigurációs fájlon keresztül. A TSToy egy olyan alkalmazás, amely felhasználói és gépi szinten konfigurálható. A DSC-erőforrásnak mindkét fájlt konfigurálnia kell.

A DSC-erőforrásnak lehetővé kell tennie a felhasználók számára a következőket:

  • Az általuk felügyelett konfiguráció hatóköre, vagy MachineUser
  • A konfigurációs fájl létezhet-e
  • A TSToy automatikus frissítése
  • Milyen gyakran ellenőrizze a TSToy a frissítéseket 1 és 90 nap között

Adja hozzá a ConfigurationScope tulajdonságot

A vagy User konfigurációs Machine fájl kezeléséhez meg kell határoznia a DSC-erőforrás egyik tulajdonságát. Az erőforrás tulajdonságának $ConfigurationScope meghatározásához adja hozzá a következő kódot a osztályhoz a metódusok előtt:

[DscProperty(Key)] [TailspinScope]
$ConfigurationScope

Ez a kód a DSC-erőforrás Kulcs tulajdonságaként definiálható$ConfigurationScope. A Kulcs tulajdonság a DSC-erőforrás egy példányának egyedi azonosítására szolgál. A tulajdonság hozzáadása megfelel a DscResource attribútum által az osztály szerkezetének létrehozásakor figyelmeztetett követelmények egyikének.

Azt is megadja, hogy $ConfigurationScopea típusa TailspinScope. A TailspinScope típusának meghatározásához adja hozzá a következő TailspinScope enumerálást a osztálydefiníció után a fájlbanExampleResources.psm1:

enum TailspinScope {
    Machine
    User
}

Ez az enumerálás teszi és MachineUser az egyetlen érvényes értéket a $ConfigurationScope DSC-erőforrás tulajdonságához.

Adja hozzá az Ensure tulajdonságot

Az ajánlott eljárás egy $Ensure tulajdonság definiálása annak szabályozására, hogy létezik-e egy DSC-erőforráspéldány. Egy $Ensure tulajdonságnak általában két érvényes értéke van, Absent és Present.

  • Ha $Ensure a(z) értéket adja meg, Presenta DSC-erőforrás létrehozza az elemet, ha az nem létezik.
  • Ha $Ensure az , Absentakkor a DSC-erőforrás törli az elemet, ha létezik.

A Tailspin DSC-erőforrás esetében a létrehozandó vagy törölni kívánt elem a megadott $ConfigurationScopekonfigurációs fájl.

A TailspinEnsure definiálása a TailspinScope után enumerálásként. A és Presenta értékekkel Absent kell rendelkeznie.

enum TailspinEnsure {
    Absent
    Present
}

Ezután adja hozzá a $Ensure tulajdonságot az osztályhoz a $ConfigurationScope tulajdonság után. Üres DscProperty attribútummal kell rendelkeznie, és a típusának TailspinEnsurenak kell lennie. Alapértelmezés szerint a értéknek kell lennie.Present

[DscProperty()] [TailspinEnsure]
$Ensure = [TailspinEnsure]::Present

Az UpdateAutomatically tulajdonság hozzáadása

Az automatikus frissítések kezeléséhez definiálja a tulajdonságot a $UpdateAutomatically tulajdonság utáni $Ensure osztályban. A DscProperty attribútumnak azt kell jeleznie, hogy kötelező, és a típusának logikainak kell lennie.

[DscProperty(Mandatory)] [bool]
$UpdateAutomatically

Az UpdateFrequency tulajdonság hozzáadása

Annak kezeléséhez, hogy a TSToy milyen gyakran keressen frissítéseket, adja hozzá a $UpdateFrequency tulajdonságot a $UpdateAutomatically tulajdonság utáni osztályhoz. Üres DscProperty attribútummal kell rendelkeznie, és a típusának intnek kell lennie. A ValidateRange attribútummal az érvényes értékeket $UpdateFrequency 1 és 90 közé korlátozhatja.

[DscProperty()] [int] [ValidateRange(1, 90)]
$UpdateFrequency

Az Okok tulajdonság hozzáadása

Mivel ez a DSC-erőforrás az Azure Automanage gépkonfigurációs funkciójával való használatra készült, a következő követelményeknek megfelelő Reasons tulajdonsággal kell rendelkeznie:

  • A DscProperty attribútum NotConfigurable tulajdonságával kell deklarálni.
  • Olyan objektumtömbnek kell lennie, amely tartalmaz egy Code nevű String tulajdonságot, egy Phrase nevű String tulajdonságot, és nincs más tulajdonsága.

A gépkonfiguráció a Reasons (Okok ) tulajdonság használatával szabványosítja a megfelelőségi információk megjelenítési módját. Az Reasons (Okok) tulajdonság metódusa által Get() visszaadott objektumok azonosítják, hogy a DSC-erőforrás egy példánya miért nem megfelelő.

A gépkonfiguráció a Reasons (Okok ) tulajdonság használatával szabványosítja a megfelelőségi információk megjelenítési módját. Az Reasons (Okok) tulajdonság metódusa által Get() visszaadott objektumok azonosítják a DSC-erőforrás egyik tulajdonságát, a kívánt állapotát és tényleges állapotát.

Az Okok tulajdonság meghatározásához definiálnia kell egy osztályt. Adja meg az ExampleResourcesReason osztályt a TailspinEnsure enumerálás után. A Kód és a Kifejezés tulajdonságnak sztringként kell lennie. Mindkét tulajdonságnak rendelkeznie kell a DscProperty attribútummal.

Annak érdekében, hogy az okok olvashatóbbak legyenek a manuális tesztelés során, határozza meg a ToString() metódust az ExampleResourcesReason osztályban a kódrészletben látható módon.

class ExampleResourcesReason {
    [DscProperty()]
    [string] $Code

    [DscProperty()]
    [string] $Phrase

    [string] ToString() {
        return "`n$($this.Code):`n`t$($this.Phrase)`n"
    }
}

Ezután adja hozzá a $Reasons tulajdonságot a DSC-erőforrás osztályához a $UpdateFrequency tulajdonság után. A beállításhoz NotConfigurable meg kell adni a DscProperty attribútumot, a típusa pedig ExampleResourcesReason[].

[DscProperty(NotConfigurable)] [ExampleResourcesReason[]]
$Reasons

Rejtett gyorsítótár tulajdonságainak hozzáadása

Ezután adjon hozzá két rejtett tulajdonságot az erőforrás aktuális állapotának gyorsítótárazására: $CachedCurrentState és $CachedData. Állítsa a típust $CachedCurrentStateTailspin értékre, amely megegyezik a osztály és a metódus visszatérési típusával Get() . Állítsa a típust $CachedDataPSCustomObject értékre. Mindkét tulajdonság előtagja a hidden kulcsszóval. Ne adja meg a DscProperty attribútumot sem.

hidden [Tailspin] $CachedCurrentState
hidden [PSCustomObject] $CachedData

Ezeket a rejtett tulajdonságokat a és Set() a Get() metódusok használják, amelyeket később definiál.

A modulfájl áttekintése

Ezen a ponton meg kell határoznia a ExampleResources.psm1 következőket:

  • A Tailspin osztály a következő tulajdonságokkal: $ConfigurationScope, $Ensure, $UpdateAutomaticallyés $UpdateFrequency
  • A TailspinScope enumerálás a és a MachineUser
  • A TailspinEnsure enumerálás értéke és PresentAbsent
  • A , Test()és Set() metódusok minimális implementációiGet().
[DscResource()]
class Tailspin {
    [DscProperty(Key)] [TailspinScope]
    $ConfigurationScope

    [DscProperty()] [TailspinEnsure]
    $Ensure = [TailspinEnsure]::Present

    [DscProperty(Mandatory)] [bool]
    $UpdateAutomatically

    [DscProperty()] [int] [ValidateRange(1,90)]
    $UpdateFrequency

    [DscProperty(NotConfigurable)] [ExampleResourcesReason[]]
    $Reasons

    hidden [Tailspin] $CachedCurrentState
    hidden [PSCustomObject] $CachedData

    [Tailspin] Get() {
        $CurrentState = [Tailspin]::new()
        return $CurrentState
    }

    [bool] Test() {
        $InDesiredState = $true
        return $InDesiredState
    }

    [void] Set() {}
}

enum TailspinScope {
    Machine
    User
}

enum TailspinEnsure {
    Absent
    Present
}

class ExampleResourcesReason {
    [DscProperty()]
    [string] $Code

    [DscProperty()]
    [string] $Phrase

    [string] ToString() {
        return "`n$($this.Code):`n`t$($this.Phrase)`n"
    }
}

Most, hogy a DSC-erőforrás megfelel a követelményeknek, a használatával Get-DscResource megtekintheti. A VS Code-ban nyisson meg egy új PowerShell-terminált.

. ./Helpers.ps1
Get-DscResource -Name Tailspin -Module ExampleResources | Format-List
Get-DscResource -Name Tailspin -Module ExampleResources -Syntax
ImplementationDetail : ClassBased
ResourceType         : Tailspin
Name                 : Tailspin
FriendlyName         :
Module               : ExampleResources
ModuleName           : ExampleResources
Version              : 0.0.1
Path                 : C:\code\dsc\ExampleResources\ExampleResources.psd1
ParentPath           : C:\code\dsc\ExampleResources
ImplementedAs        : PowerShell
CompanyName          : Unknown
Properties           : {ConfigurationScope, UpdateAutomatically, DependsOn, Ensure…}

Tailspin [String] #ResourceName
{
    ConfigurationScope = [string]{ Machine | User }
    UpdateAutomatically = [bool]
    [DependsOn = [string[]]]
    [Ensure = [string]{ Absent | Present }]
    [PsDscRunAsCredential = [PSCredential]]
    [UpdateFrequency = [Int32]]
}

4 – A DSC-erőforrás metódusainak implementálása

A DSC-erőforrás metódusai határozzák meg, hogyan lehet lekérni egy DSC-erőforrás aktuális állapotát, ellenőrizni a kívánt állapotot, és kikényszeríteni a kívánt állapotot.

A Get metódus

A Get() metódus lekéri a DSC-erőforrás aktuális állapotát. Egy DSC-erőforrás manuális vizsgálatára szolgál, és a Test() metódus meghívja.

A Get() metódus nem rendelkezik paraméterekkel, és a osztály egy példányát adja vissza kimenetként. A Tailspin DSC-erőforrás minimális implementációja a következőképpen néz ki:

[Tailspin] Get() {
    $CurrentState = [Tailspin]::new()
    return $CurrentState
}

Ez az implementáció csak a Tailspin osztály egy példányát hozza létre és adja vissza. Ennek a viselkedésnek a megtekintéséhez meghívhatja a metódust a használatával Invoke-DscResource .

Invoke-DscResource -Name Tailspin -Module ExampleResources -Method Get -Property @{
    ConfigurationScope  = 'User'
    UpdateAutomatically = $true
}
ConfigurationScope  Ensure UpdateAutomatically UpdateFrequency
------------------  ------ ------------------- ---------------
           Machine Present               False               0

A visszaadott objektum tulajdonságai mind az alapértelmezett értékre vannak beállítva. A értékének $ConfigurationScope mindig a felhasználó által megadott értéknek kell lennie. Ahhoz, hogy a Get() metódus hasznos legyen, a DSC-erőforrás tényleges állapotát kell visszaadnia.

[Tailspin] Get() {
    $CurrentState = [Tailspin]::new()

    $CurrentState.ConfigurationScope = $this.ConfigurationScope

    $this.CachedCurrentState = $CurrentState

    return $CurrentState
}

A $this változó a DSC-erőforrás munkapéldányára hivatkozik. Most, ha ismét használja Invoke-DscResource , $ConfigurationScope a megfelelő értékkel rendelkezik.

Invoke-DscResource -Name Tailspin -Module ExampleResources -Method Get -Property @{
    ConfigurationScope  = 'User'
    UpdateAutomatically = $true
}
ConfigurationScope  Ensure UpdateAutomatically UpdateFrequency
------------------  ------ ------------------- ---------------
              User Present               False               0

Ezután a DSC-erőforrásnak meg kell határoznia, hogy létezik-e a konfigurációs fájl. Ha igen, $Ensure akkor a legyen Present. Ha nem, $Ensure akkor a legyen Absent.

A TSToy konfigurációs fájljainak helye az operációs rendszertől és a konfiguráció hatókörétől függ:

  • Windowsos gépek esetén:
    • A Machine konfigurációs fájl a következő: %PROGRAMDATA%\TailSpinToys\tstoy\tstoy.config.json
    • A User konfigurációs fájl a következő: %APPDATA%\TailSpinToys\tstoy\tstoy.config.json
  • Linux rendszerű gépek esetén:
    • A Machine konfigurációs fájl a következő: /etc/xdg/TailSpinToys/tstoy/tstoy.config.json
    • A User konfigurációs fájl a következő: ~/.config/TailSpinToys/tstoy/tstoy.config.json
  • MacOS-gépek esetén:
    • A Machine konfigurációs fájl a következő: /Library/Preferences/TailSpinToys/tstoy/tstoy.config.json
    • A User konfigurációs fájl a következő: ~/Library/Preferences/TailSpinToys/tstoy/tstoy.config.json

Ezeknek az elérési utaknak a kezeléséhez létre kell hoznia egy segédmetódust( GetConfigurationFile()).

[string] GetConfigurationFile() {
    $FilePaths = @{
        Linux = @{
            Machine   = '/etc/xdg/TailSpinToys/tstoy/tstoy.config.json'
            User      = '~/.config/TailSpinToys/tstoy/tstoy.config.json'
        }
        MacOS = @{
            Machine   = '/Library/Preferences/TailSpinToys/tstoy/tstoy.config.json'
            User      = '~/Library/Preferences/TailSpinToys/tstoy/tstoy.config.json'
        }
        Windows = @{
            Machine = "$env:ProgramData\TailSpinToys\tstoy\tstoy.config.json"
            User    = "$env:APPDATA\TailSpinToys\tstoy\tstoy.config.json"
        }
    }

    $Scope = $this.ConfigurationScope.ToString()

    if ($Global:PSVersionTable.PSVersion.Major -lt 6 -or $Global:IsWindows) {
        return $FilePaths.Windows.$Scope
    } elseif ($Global:IsLinux) {
        return $FilePaths.Linux.$Scope
    } else {
        return $FilePaths.MacOS.$Scope
    }
}

Az új metódus teszteléséhez hajtsa végre az utasítást az usingExampleResources modul osztályainak és számainak az aktuális munkamenetbe való betöltéséhez.

using module ./ExampleResources.psd1
$Example = [Tailspin]::new()
$Example
$Example.GetConfigurationFile()
$Example.ConfigurationScope = 'User'
$Example.GetConfigurationFile()
Ensure  ConfigurationScope UpdateAutomatically UpdateFrequency
------- ------------------ ------------------- ---------------
Present            Machine               False               0

C:\ProgramData\TailSpinToys\tstoy\tstoy.config.json

C:\Users\mikey\AppData\Roaming\TailSpinToys\tstoy\tstoy.config.json

Nyissa meg Helpers.ps1 a VS Code-ban. Másolja és illessze be a konfigurációs fájlok elérési útját a szkriptbe, és rendelje hozzá őket a és $TSToyUserPatha fájlhoz$TSToyMachinePath. A fájlnak a következőhöz kell hasonlítania:

$env:PSModulePath += "<separator>$pwd"
$TSToyMachinePath = '<machine configuration file path>'
$TSToyUserPath = '<user configuration file path>'

Lépjen ki a terminálból a VS Code-ban, és nyisson meg egy új terminált. Pont-forrás Helpers.ps1.

. ./Helpers.ps1

Most már megírhatja a metódus többi részét Get() .

[Tailspin] Get() {
    $CurrentState = [Tailspin]::new()

    $CurrentState.ConfigurationScope = $this.ConfigurationScope

    $FilePath = $this.GetConfigurationFile()

    if (!(Test-Path -Path $FilePath)) {
        $CurrentState.Ensure = [TailspinEnsure]::Absent

        $this.CachedCurrentState = $CurrentState

        return $CurrentState
    }

    $Data = Get-Content -Raw -Path $FilePath |
        ConvertFrom-Json -ErrorAction Stop

    $this.CachedData = $Data

    if ($null -ne $Data.Updates.Automatic) {
        $CurrentState.UpdateAutomatically = $Data.Updates.Automatic
    }

    if ($null -ne $Data.Updates.CheckFrequency) {
        $CurrentState.UpdateFrequency = $Data.Updates.CheckFrequency
    }

    $this.CachedCurrentState = $CurrentState

    return $CurrentState
}

A konfigurációs fájl elérési útjának beállítása $ConfigurationScope és meghatározása után a metódus ellenőrzi, hogy létezik-e a fájl. Ha nem létezik, csak az eredményre kell Absent beállítania $Ensure és visszaadnia az eredményt.

Ha a fájl létezik, a metódusnak JSON-ból kell konvertálnia a tartalmat a konfiguráció aktuális állapotának létrehozásához. Ezután a metódus ellenőrzi, hogy a kulcsok rendelkeznek-e értékkel, mielőtt hozzárendeli őket az aktuális állapot tulajdonságaihoz. Ha nincsenek megadva, a DSC-erőforrásnak figyelembe kell vennie a halmazt, és az alapértelmezett állapotban kell lennie.

Ekkor a DSC-erőforrás gyorsítótárazza az adatokat. Az adatok gyorsítótárazásával megvizsgálhatja az adatokat a fejlesztés során, és hasznos lehet a Set() módszer implementálásakor.

Ezt a viselkedést helyileg ellenőrizheti.

$GetParameters = @{
    Name     = 'Tailspin'
    Module   = 'ExampleResources'
    Method   = 'Get'
    Property = @{
        ConfigurationScope = 'User'
    }
}

Invoke-DscResource @GetParameters
New-Item -Path $TSToyUserPath -Force
Invoke-DscResource @GetParameters
ConfigurationScope Ensure UpdateAutomatically UpdateFrequency
------------------ ------ ------------------- ---------------
              User Absent               False               0

    Directory: C:\Users\mikey\AppData\Roaming\TailSpinToys\tstoy

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           9/15/2022  3:43 PM              0 tstoy.config.json

ConfigurationScope  Ensure UpdateAutomatically UpdateFrequency
------------------  ------ ------------------- ---------------
              User Present               False               0

Nyissa meg a User hatókörkonfigurációs fájlt a VS Code-ban.

code $TSToyUserPath

Másolja ezt a JSON-konfigurációt a fájlba, és mentse.

{
    "unmanaged_key": true,
    "updates": {
        "automatic": true,
        "checkFrequency": 30
    }
}

Hívja Invoke-DscResource meg újra, és tekintse meg az eredményekben tükröződő értékeket.

Invoke-DscResource @GetParameters
ConfigurationScope  Ensure UpdateAutomatically UpdateFrequency
------------------  ------ ------------------- ---------------
              User Present                True              30

A Get() metódus mostantól pontos információkat ad vissza a DSC-erőforrás aktuális állapotáról.

Kezelési okok

A gépkonfigurációval kompatibilis DSC-erőforrások esetében a Get() metódusnak a Reasons tulajdonságot is fel kell töltenie. Ehhez hozza létre a metódust GetReasons() . Egy ExampleResourcesReason objektumból álló tömböt kell visszaadnia, és egyetlen Tailspin-objektumot kell bemenetként vennie.

[ExampleResourcesReason[]] GetReasons([Tailspin]$CurrentState) {
    [ExampleResourcesReason[]]$DefinedReasons = @()

    return $DefinedReasons
}

Ezután a metódusnak ellenőriznie kell az egyes konfigurálható beállítások érvényességét. Minden beállításhoz a metódusnak egy ExampleResourcesReason értéket kell visszaadnia, amely azonosítja és leírja az állapotot.

Az első ellenőrizendő beállítás a $Ensure tulajdonság. Ha $Ensure nincs állapotban, az összes többi tulajdonság helytelen lesz, mivel a konfigurációs fájl akkor létezik, amikor nem kellene, vagy nem is létezik, amikor szükséges.

A metódusnak meg kell határoznia egy okot a megfelelő kóddal és egy értelmes kifejezéssel. A kód mindig a formátumban <ResourceName>.<ResourceName>.<PropertyName>van. A Kifejezés mindig az ellenőrzést leíró mondat, amelyet a várt állapotot és a tényleges állapotot leíró mondatok követnek.

[ExampleResourcesReason[]] GetReasons([Tailspin]$CurrentState) {
    [ExampleResourcesReason[]]$DefinedReasons = @()

    $FilePath = $this.GetConfigurationFile()

    if ($this.Ensure -eq [TailspinEnsure]::Present) {
        $Expected = "Expected configuration file to exist at '$FilePath'."
    } else {
        $Expected = "Expected configuration file not to exist at '$FilePath'."
    }

    if ($CurrentState.Ensure -eq [TailspinEnsure]::Present) {
        $Actual = "The configuration file exists at '$FilePath'."
    } else {
        $Actual = "The configuration file was not found at '$FilePath'."
    }

    $DefinedReasons += [ExampleResourcesReason]@{
        Code   = "Tailspin.Tailspin.Ensure"
        Phrase = @(
            "Checked existence of the TSToy configuration file in the $($this.ConfigurationScope) scope."
            $Expected
            $Actual
        ) -join "`n`t"
    }

    if ($CurrentState.Ensure -ne $this.Ensure) {
        return $DefinedReasons
    }

    return $DefinedReasons
}

Ha $Ensure nincs állapotban, a metódusnak ellenőriznie kell, hogy a kívánt állapot-e Absent. Ha igen, nincs más tulajdonság, amely nem lehet állapotban, mert a konfigurációs fájl nem létezik, és nem is létezhet.

[ExampleResourcesReason[]] GetReasons([Tailspin]$CurrentState) {
    [ExampleResourcesReason[]]$DefinedReasons = @()

    $FilePath = $this.GetConfigurationFile()

    if ($this.Ensure -eq [TailspinEnsure]::Present) {
        $Expected = "Expected configuration file to exist at '$FilePath'."
    } else {
        $Expected = "Expected configuration file not to exist at '$FilePath'."
    }

    if ($CurrentState.Ensure -eq [TailspinEnsure]::Present) {
        $Actual = "The configuration file exists at '$FilePath'."
    } else {
        $Actual = "The configuration file was not found at '$FilePath'."
    }

    $DefinedReasons += [ExampleResourcesReason]@{
        Code   = "Tailspin.Tailspin.Ensure"
        Phrase = @(
            "Checked existence of the TSToy configuration file in the $($this.ConfigurationScope) scope."
            $Expected
            $Actual
        ) -join "`n`t"
    }

    if ($CurrentState.Ensure -ne $this.Ensure) {
        return $DefinedReasons
    }

    if ($CurrentState.Ensure -eq [TailspinEnsure]::Absent) {
        return $DefinedReasons
    }

    return $DefinedReasons
}

Ha $Ensure igen Present , és a fájl létezik, a metódusnak ellenőriznie kell a fennmaradó konfigurálható tulajdonságokat.

$UpdateAutomatically A tulajdonság ellenőrzése egyszerű, mivel kötelező és logikai érték.

[ExampleResourcesReason[]] GetReasons([Tailspin]$CurrentState) {
    [ExampleResourcesReason[]]$DefinedReasons = @()

    $FilePath = $this.GetConfigurationFile()

    if ($this.Ensure -eq [TailspinEnsure]::Present) {
        $Expected = "Expected configuration file to exist at '$FilePath'."
    } else {
        $Expected = "Expected configuration file not to exist at '$FilePath'."
    }

    if ($CurrentState.Ensure -eq [TailspinEnsure]::Present) {
        $Actual = "The configuration file exists at '$FilePath'."
    } else {
        $Actual = "The configuration file was not found at '$FilePath'."
    }

    $DefinedReasons += [ExampleResourcesReason]@{
        Code   = "Tailspin.Tailspin.Ensure"
        Phrase = @(
            "Checked existence of the TSToy configuration file in the $($this.ConfigurationScope) scope."
            $Expected
            $Actual
        ) -join "`n`t"
    }

    if ($CurrentState.Ensure -ne $this.Ensure) {
        return $DefinedReasons
    }

    if ($CurrentState.Ensure -eq [TailspinEnsure]::Absent) {
        return $DefinedReasons
    }

    $DefinedReasons += [ExampleResourcesReason]@{
        Code   = "Tailspin.Tailspin.UpdateAutomatically"
        Phrase = (@(
                "Checked value of the 'updates.automatic' key in the TSToy configuration file."
                "Expected boolean value of '$($this.UpdateAutomatically)'"
                "Actual boolean value of '$($CurrentState.UpdateAutomatically)'"
            ) -join "`n`t")
    }

    return $DefinedReasons
}

Az utolsó ellenőrizendő tulajdonság a következő $UpdateFrequency: . Ez az ellenőrzés rövidre zárható, ha a tulajdonság 0értéke . Ha a tulajdonság meg van adva, az mindig 1 és 90 között lesz, ami azt 0 jelenti, hogy a tulajdonság nincs felügyelve.

[ExampleResourcesReason[]] GetReasons([Tailspin]$CurrentState) {
    [ExampleResourcesReason[]]$DefinedReasons = @()

    $FilePath = $this.GetConfigurationFile()

    if ($this.Ensure -eq [TailspinEnsure]::Present) {
        $Expected = "Expected configuration file to exist at '$FilePath'."
    } else {
        $Expected = "Expected configuration file not to exist at '$FilePath'."
    }

    if ($CurrentState.Ensure -eq [TailspinEnsure]::Present) {
        $Actual = "The configuration file exists at '$FilePath'."
    } else {
        $Actual = "The configuration file was not found at '$FilePath'."
    }

    $DefinedReasons += [ExampleResourcesReason]@{
        Code   = "Tailspin.Tailspin.Ensure"
        Phrase = @(
            "Checked existence of the TSToy configuration file in the $($this.ConfigurationScope) scope."
            $Expected
            $Actual
        ) -join "`n`t"
    }

    if ($CurrentState.Ensure -ne $this.Ensure) {
        return $DefinedReasons
    }

    if ($CurrentState.Ensure -eq [TailspinEnsure]::Absent) {
        return $DefinedReasons
    }

    $DefinedReasons += [ExampleResourcesReason]@{
        Code   = "Tailspin.Tailspin.UpdateAutomatically"
        Phrase = (@(
                "Checked value of the 'updates.automatic' key in the TSToy configuration file."
                "Expected boolean value of '$($this.UpdateAutomatically)'"
                "Actual boolean value of '$($CurrentState.UpdateAutomatically)'"
            ) -join "`n`t")
    }

    return $DefinedReasons

    # Short-circuit the check; UpdateFrequency isn't defined by caller
    if ($this.UpdateFrequency -eq 0) {
        return $DefinedReasons
    }
}

Végül a metódusnak össze kell hasonlítania a tulajdonság kívánt és aktuális állapotát $UpdateFrequency , és meg kell határoznia annak okát, ha az állapoton kívül vannak.

[ExampleResourcesReason[]] GetReasons([Tailspin]$CurrentState) {
    [ExampleResourcesReason[]]$DefinedReasons = @()

    $FilePath = $this.GetConfigurationFile()

    if ($this.Ensure -eq [TailspinEnsure]::Present) {
        $Expected = "Expected configuration file to exist at '$FilePath'."
    } else {
        $Expected = "Expected configuration file not to exist at '$FilePath'."
    }

    if ($CurrentState.Ensure -eq [TailspinEnsure]::Present) {
        $Actual = "The configuration file exists at '$FilePath'."
    } else {
        $Actual = "The configuration file was not found at '$FilePath'."
    }

    $DefinedReasons += [ExampleResourcesReason]@{
        Code   = "Tailspin.Tailspin.Ensure"
        Phrase = @(
            "Checked existence of the TSToy configuration file in the $($this.ConfigurationScope) scope."
            $Expected
            $Actual
        ) -join "`n`t"
    }

    if ($CurrentState.Ensure -ne $this.Ensure) {
        return $DefinedReasons
    }

    if ($CurrentState.Ensure -eq [TailspinEnsure]::Absent) {
        return $DefinedReasons
    }

    $DefinedReasons += [ExampleResourcesReason]@{
        Code   = "Tailspin.Tailspin.UpdateAutomatically"
        Phrase = (@(
                "Checked value of the 'updates.automatic' key in the TSToy configuration file."
                "Expected boolean value of '$($this.UpdateAutomatically)'"
                "Actual boolean value of '$($CurrentState.UpdateAutomatically)'"
            ) -join "`n`t")
    }

    # Short-circuit the check; UpdateFrequency isn't defined by caller
    if ($this.UpdateFrequency -eq 0) {
        return $DefinedReasons
    }

    $DefinedReasons += [ExampleResourcesReason]@{
        Code   = "Tailspin.Tailspin.UpdateFrequency"
        Phrase = (@(
                "Checked value of the 'updates.checkFrequency' key in the TSToy configuration file."
                "Expected integer value of '$($this.UpdateFrequency)'."
                "Actual integer value of '$($CurrentState.UpdateFrequency)'."
            ) -join "`n`t")
    }

    return $DefinedReasons
}

GetReasons() A metódus implementálásával frissíteni kell a Get() metódust, hogy meghívja, mielőtt visszaadja az aktuális állapotot.

[Tailspin] Get() {
    $CurrentState = [Tailspin]::new()

    $CurrentState.ConfigurationScope = $this.ConfigurationScope

    $FilePath = $this.GetConfigurationFile()

    if (!(Test-Path -Path $FilePath)) {
        $CurrentState.Ensure = [TailspinEnsure]::Absent
        $CurrentState.Reasons = $this.GetReasons($CurrentState)

        $this.CachedCurrentState = $CurrentState

        return $CurrentState
    }

    $Data = Get-Content -Raw -Path $FilePath |
    ConvertFrom-Json -ErrorAction Stop

    $this.CachedData = $Data

    if ($null -ne $Data.Updates.Automatic) {
        $CurrentState.UpdateAutomatically = $Data.Updates.Automatic
    }

    if ($null -ne $Data.Updates.CheckFrequency) {
        $CurrentState.UpdateFrequency = $Data.Updates.CheckFrequency
    }

    $CurrentState.Reasons = $this.GetReasons($CurrentState)

    $this.CachedCurrentState = $CurrentState

    return $CurrentState
}

Az implementáció frissítésével ellenőrizheti a viselkedést, és láthatja, hogy az okok a következők:

$SharedParameters = @{
    Name     = 'Tailspin'
    Module   = 'ExampleResources'
    Property = @{
        ConfigurationScope  = 'User'
        Ensure              = 'Present'
        UpdateAutomatically = $false
    }
}

Invoke-DscResource -Method Get @SharedParameters

$SharedParameters.Property.UpdateAutomatically = $true
Invoke-DscResource -Method Get @SharedParameters

$SharedParameters.Property.UpdateFrequency = 1
Invoke-DscResource -Method Get @SharedParameters
ConfigurationScope  : User
Ensure              : Present
UpdateAutomatically : True
UpdateFrequency     : 1
Reasons             : {
                      Tailspin.Tailspin.Ensure:
                        Checked existence of the TSToy configuration file in
                      the User scope.
                        Expected configuration file to exist at 'C:\Users\mlomba
                      rdi\AppData\Roaming\TailSpinToys\tstoy\tstoy.config.json'
                      .
                        The configuration file exists at 'C:\Users\mlombardi\App
                      Data\Roaming\TailSpinToys\tstoy\tstoy.config.json'.
                      ,
                      Tailspin.Tailspin.UpdateAutomatically:
                        Checked value of the 'updates.automatic' key in the
                      TSToy configuration file.
                        Expected boolean value of 'False'
                        Actual boolean value of 'True'
                      }

ConfigurationScope  : User
Ensure              : Present
UpdateAutomatically : True
UpdateFrequency     : 1
Reasons             : {
                      Tailspin.Tailspin.Ensure:
                        Checked existence of the TSToy configuration file in
                      the User scope.
                        Expected configuration file to exist at 'C:\Users\mlomba
                      rdi\AppData\Roaming\TailSpinToys\tstoy\tstoy.config.json'
                      .
                        The configuration file exists at 'C:\Users\mlombardi\App
                      Data\Roaming\TailSpinToys\tstoy\tstoy.config.json'.
                      ,
                      Tailspin.Tailspin.UpdateAutomatically:
                        Checked value of the 'updates.automatic' key in the
                      TSToy configuration file.
                        Expected boolean value of 'True'
                        Actual boolean value of 'True'
                      }

ConfigurationScope  : User
Ensure              : Present
UpdateAutomatically : True
UpdateFrequency     : 1
Reasons             : {
                      Tailspin.Tailspin.Ensure:
                        Checked existence of the TSToy configuration file in
                      the User scope.
                        Expected configuration file to exist at 'C:\Users\mlomba
                      rdi\AppData\Roaming\TailSpinToys\tstoy\tstoy.config.json'
                      .
                        The configuration file exists at 'C:\Users\mlombardi\App
                      Data\Roaming\TailSpinToys\tstoy\tstoy.config.json'.
                      ,
                      Tailspin.Tailspin.UpdateAutomatically:
                        Checked value of the 'updates.automatic' key in the
                      TSToy configuration file.
                        Expected boolean value of 'True'
                        Actual boolean value of 'True'
                      ,
                      Tailspin.Tailspin.UpdateFrequency:
                        Checked value of the 'updates.checkFrequency' key in
                      the TSToy configuration file.
                        Expected integer value of '1'.
                        Actual integer value of '1'.
                      }

A Test metódus

Get() A metódus implementálásával ellenőrizheti, hogy az aktuális állapot megfelel-e a kívánt állapotnak.

A Test() metódusok minimális implementációja mindig a értéket adja $truevissza.

[bool] Test() {
    return $true
}

Ezt a parancs futtatásával Invoke-DscResourceellenőrizheti.

$SharedParameters = @{
    Name     = 'Tailspin'
    Module   = 'ExampleResources'
    Property = @{
        ConfigurationScope = 'User'
        UpdateAutomatically = $false
    }
}

Invoke-DscResource -Method Get @SharedParameters
Invoke-DscResource -Method Test @SharedParameters
ConfigurationScope  Ensure UpdateAutomatically UpdateFrequency
------------------  ------ ------------------- ---------------
              User Present                True              30

InDesiredState
--------------
          True

A metódust pontosan tükröznie kell Test() , hogy a DSC-erőforrás a kívánt állapotban van-e. A Test() metódusnak mindig meg kell hívnia a Get() metódust, hogy az aktuális állapotot hasonlítsa össze a kívánt állapottal. Ezután ellenőrizze, hogy a $Ensure tulajdonság helyes-e. Ha nem, azonnal térjen vissza $false . Nincs szükség további ellenőrzésekre, ha a $Ensure tulajdonság nem a kívánt állapotban van.

[bool] Test() {
    $CurrentState = $this.Get()

    if ($CurrentState.Ensure -ne $this.Ensure) {
        return $false
    }

    return $true
}

Most már ellenőrizheti a frissített viselkedést.

$TestParameters = @{
    Name     = 'Tailspin'
    Module   = 'ExampleResources'
    Property = @{
        ConfigurationScope  = 'User'
        UpdateAutomatically = $false
        Ensure              = 'Absent'
    }
}

Invoke-DscResource -Method Test @TestParameters

$TestParameters.Property.Ensure = 'Present'

Invoke-DscResource -Method Test @TestParameters
InDesiredState
--------------
         False

InDesiredState
--------------
          True

Ezután ellenőrizze, hogy a értéke $Ensure .Absent Ha a konfigurációs fájl nem létezik, és nem is kellene léteznie, nincs ok a fennmaradó tulajdonságok ellenőrzésére.

[bool] Test() {
    $CurrentState = $this.Get()

    if ($CurrentState.Ensure -ne $this.Ensure) {
        return $false
    }

    if ($CurrentState.Ensure -eq [TailspinEnsure]::Absent) {
        return $true
    }

    return $true
}

Ezután a metódusnak össze kell hasonlítania a TSToy frissítési viselkedését kezelő tulajdonságok aktuális állapotát. Először ellenőrizze, hogy a $UpdateAutomatically tulajdonság megfelelő állapotban van-e. Ha nem, adja vissza a értéket $false.

[bool] Test() {
    $CurrentState = $this.Get()

    if ($CurrentState.Ensure -ne $this.Ensure) {
        return $false
    }

    if ($CurrentState.Ensure -eq [TailspinEnsure]::Absent) {
        return $true
    }

    if ($CurrentState.UpdateAutomatically -ne $this.UpdateAutomatically) {
        return $false
    }

    return $true
}

Az összehasonlításhoz $UpdateFrequencymeg kell határoznunk, hogy a felhasználó megadta-e az értéket. Mivel $UpdateFrequency a tulajdonság inicializálva 0 van, és a tulajdonság ValidateRange attribútuma azt határozza meg, hogy a és 90között 1 kell lennie, tudjuk, hogy a értéke 0 azt jelzi, hogy a tulajdonság nincs megadva.

Ezzel az információval a metódusnak a Test() következőket kell használnia:

  1. Visszatérés $true , ha a felhasználó nem adta meg $UpdateFrequency
  2. Visszaadja $false , ha a felhasználó megadta $UpdateFrequency , és a rendszer értéke nem egyezik meg a felhasználó által megadott értékkel
  3. Visszatérés $true , ha egyik korábbi feltétel sem teljesült
[bool] Test() {
    $CurrentState = $this.Get()

    if ($CurrentState.Ensure -ne $this.Ensure) {
        return $false
    }

    if ($CurrentState.Ensure -eq [TailspinEnsure]::Absent) {
        return $true
    }

    if ($CurrentState.UpdateAutomatically -ne $this.UpdateAutomatically) {
        return $false
    }

    if ($this.UpdateFrequency -eq 0) {
        return $true
    }

    if ($CurrentState.UpdateFrequency -ne $this.UpdateFrequency) {
        return $false
    }

    return $true
}

A metódus most a Test() következő műveleti sorrendet használja:

  1. Kérje le a TSToy konfigurációjának aktuális állapotát.
  2. Akkor adja vissza $false , ha a konfiguráció létezik, amikor nem szabad vagy nem létezik, amikor szükséges.
  3. Adja vissza $true , ha a konfiguráció nem létezik, és nem is létezhet.
  4. Akkor adja vissza $false , ha a konfiguráció automatikus frissítési beállítása nem egyezik meg a kívánt beállítással.
  5. Visszaadja $true , ha a felhasználó nem adott meg értéket a frissítési gyakoriság beállításához.
  6. Visszaadja $false , ha a felhasználó megadott értéke nem egyezik meg a konfiguráció beállításával.
  7. Akkor adja vissza $true , ha a korábbi feltételek egyike sem teljesült.

A metódust Test() helyileg ellenőrizheti:

$SharedParameters = @{
    Name     = 'Tailspin'
    Module   = 'ExampleResources'
    Property = @{
        ConfigurationScope  = 'User'
        Ensure              = 'Present'
        UpdateAutomatically = $false
    }
}

Invoke-DscResource -Method Get @SharedParameters

Invoke-DscResource -Method Test @SharedParameters

$SharedParameters.Property.UpdateAutomatically = $true
Invoke-DscResource -Method Test @SharedParameters

$SharedParameters.Property.UpdateFrequency = 1
Invoke-DscResource -Method Test @SharedParameters
ConfigurationScope  Ensure UpdateAutomatically UpdateFrequency
------------------  ------ ------------------- ---------------
              User Present                True              30

InDesiredState
--------------
         False

InDesiredState
--------------
          True

InDesiredState
--------------
         False

Ezzel a kóddal a Test() metódus pontosan meg tudja állapítani, hogy a konfigurációs fájl a kívánt állapotban van-e.

A Set metódus

Most, hogy a és Test() a Get() metódus megbízhatóan működik, megadhatja azt a Set() metódust, amely ténylegesen kényszeríti a kívánt állapotot.

A minimális implementációban a Set() metódus nem tesz semmit.

[void] Set() {}

Először meg kell határoznia, Set() hogy létre kell-e hoznia, frissítenie vagy el kell-e távolítania a DSC-erőforrást.

[void] Set() {
    if ($this.Test()) {
            return
    }

    $CurrentState = $this.CachedCurrentState

    $IsAbsent = $CurrentState.Ensure -eq [TailspinEnsure]::Absent
    $ShouldBeAbsent = $this.Ensure -eq [TailspinEnsure]::Absent

    if ($IsAbsent) {
        # Create
    } elseif ($ShouldBeAbsent) {
        # Remove
    } else {
        # Update
    }
}

Set() először meghívja a metódust Test() annak megállapításához, hogy valóban szükség van-e valamire. Egyes eszközök, például az Azure Automanage gépkonfigurációs funkciója, biztosítják, hogy a metódus csak a Set()Test() metódus után legyen meghívva. A parancsmag használatakor Invoke-DscResource azonban nincs ilyen garancia.

Mivel a metódus meghívja Get()a Test() metódust, amely gyorsítótárazza az aktuális állapotot, a DSC-erőforrás anélkül férhet hozzá a gyorsítótárazott aktuális állapothoz, hogy újra meg kellene hívnia a metódustGet().

Ezután a DSC-erőforrásnak meg kell különböztetnie a konfigurációs fájl létrehozási, eltávolítási és frissítési viselkedését. Ha a konfigurációs fájl nem létezik, tudjuk, hogy létre kell hozni. Ha a konfigurációs fájl létezik, és nem kellene, tudjuk, hogy el kell távolítani. Ha a konfigurációs fájl létezik, és léteznie kell, tudjuk, hogy frissíteni kell.

Hozzon létre három új metódust a műveletek kezeléséhez, és szükség szerint hívja meg őket a Set() metódusban. A visszatérési típusnak mind a háromnál érvénytelennek kell lennie.

[void] Set() {
    if ($this.Test()) {
            return
    }

    $CurrentState = $this.CachedCurrentState

    $IsAbsent = $CurrentState.Ensure -eq [TailspinEnsure]::Absent
    $ShouldBeAbsent = $this.Ensure -eq [TailspinEnsure]::Absent

    if ($IsAbsent) {
        $this.Create()
    } elseif ($ShouldBeAbsent) {
        $this.Remove()
    } else {
        $this.Update()
    }
}

[void] Create() {}
[void] Remove() {}
[void] Update() {}

Hozzon létre egy nevű új metódust ToConfigJson()is. A visszatérési típusnak sztringnek kell lennie. Ez a metódus átalakítja a DSC-erőforrást a konfigurációs fájl által várt JSON-fájllá. A következő minimális implementációval kezdheti:

[string] ToConfigJson() {
    $config = @{}

    return ($config | ConvertTo-Json)
}

A ToConfigJson metódus

A minimális implementáció egy üres JSON-objektumot ad vissza sztringként. A hasznosság érdekében vissza kell adnia a TSToy konfigurációs fájljában található beállítások tényleges JSON-ábrázolását.

Először a kötelező automatikus frissítési beállítással előre kitöltse $config a kivonattáblát úgy, hogy hozzáadja a updates kulcsot a hozzá tartozó értékkel, mint kivonattáblát. A kivonattáblának rendelkeznie kell a automatic kulccsal. Rendelje hozzá az osztály tulajdonságának $UpdateAutomatically értékét a automatic kulcshoz.

[string] ToConfigJson() {
    $config = @{
        updates = @{
            automatic = $this.UpdateAutomatically
        }
    }

    return ($config | ConvertTo-Json)
}

Ez a kód lefordítja a TSToy beállításainak DSC-erőforrás-reprezentációját arra a struktúrára, amelyet a TSToy konfigurációs fájlja elvár.

Ezután a metódusnak ellenőriznie kell, hogy az osztály gyorsítótárazza-e az adatokat egy meglévő konfigurációs fájlból. A gyorsítótárazott adatok lehetővé teszik, hogy a DSC-erőforrás a nem felügyelt beállítások felülírása vagy eltávolítása nélkül kezelje a megadott beállításokat.

[string] ToConfigJson() {
    $config = @{
        updates = @{
            automatic = $this.UpdateAutomatically
        }
    }

    if ($this.CachedData) {
        # Copy unmanaged settings without changing the cached values
        $this.CachedData |
            Get-Member -MemberType NoteProperty |
            Where-Object -Property Name -NE -Value 'updates' |
            ForEach-Object -Process {
                $setting = $_.Name
                $config.$setting = $this.CachedData.$setting
            }

        # Add the checkFrequency to the hashtable if it is set in the cache
        if ($frequency = $this.CachedData.updates.checkFrequency) {
            $config.updates.checkFrequency = $frequency
        }
    }

    # If the user specified an UpdateFrequency, use that value
    if ($this.UpdateFrequency -ne 0) {
        $config.updates.checkFrequency = $this.UpdateFrequency
    }

    return ($config | ConvertTo-Json)
}

Ha a osztály gyorsítótárazza a beállításokat egy meglévő konfigurációból, akkor:

  1. Megvizsgálja a gyorsítótárazott adatok tulajdonságait, és megkeresi a DSC-erőforrás által nem kezelt tulajdonságokat. Ha talál ilyent, a metódus beszúrja ezeket a nem felügyelt tulajdonságokat a $config kivonattáblába.

    Mivel a DSC-erőforrás csak a frissítési beállításokat kezeli, a rendszer minden beállítást beszúr, kivéve azokat updates .

  2. Ellenőrzi, hogy be van-e állítva a checkFrequency beállítás updates . Ha be van állítva, a metódus beszúrja ezt az értéket a $config kivonattáblába.

    Ez a művelet lehetővé teszi, hogy a DSC-erőforrás figyelmen kívül hagyja a $UpdateFrequency tulajdonságot, ha a felhasználó nem adja meg.

  3. Végül a metódusnak ellenőriznie kell, hogy a felhasználó megadta-e a $UpdateFrequency tulajdonságot, és be kell-e szúrnia a $config kivonattáblába, ha igen.

Ezzel a kóddal a ToConfigJson() metódus:

  1. A TSToy-alkalmazás konfigurációs fájljában elvárt kívánt állapot pontos JSON-ábrázolását adja vissza
  2. Tiszteletben tartja a TSToy azon beállításait, amelyeket a DSC-erőforrás nem kezel explicit módon
  3. Tiszteletben tartja a TSToy frissítési gyakoriságának meglévő értékét, ha a felhasználó nem adott meg egyet, beleértve a konfigurációs fájlban nem definiált állapotot is

Az új metódus teszteléséhez zárja be a VS Code-terminált, és nyisson meg egy újat. using A utasítás végrehajtásával töltse be az ExampleResources modul osztályait és számait az aktuális munkamenetbe, és adja meg a szkript pontforrásáthelpers.ps1.

using module ./ExampleResources.psd1
. ./Helpers.ps1
$Example = [Tailspin]::new()
Get-Content -Path $TSToyUserPath
$Example.ConfigurationScope = 'User'
$Example.ToConfigJson()

A metódus meghívása Get() előtt a ToJsonConfig metódus kimenetében az egyetlen érték a tulajdonság konvertált értéke $UpdateAutomatically .

{
    "unmanaged_key": true,
    "updates": {
        "automatic": false,
        "checkFrequency": 30
    }
}

{
  "updates": {
    "automatic": false
  }
}
$Example.Get()
$Example.ToConfigJson()

A hívása Get()után a kimenet tartalmaz egy nem felügyelt legfelső szintű kulcsot( unmanaged_key). A meglévő beállítást is tartalmazza a konfigurációs fájlban $UpdateFrequency , mivel az nem lett explicit módon beállítva a DSC-erőforráson.

ConfigurationScope  : User
Ensure              : Present
UpdateAutomatically : False
UpdateFrequency     : 30
Reasons             : {}

{
  "unmanaged_key": true,
  "updates": {
    "automatic": false,
    "checkFrequency": 30
  }
}
$Example.UpdateFrequency = 7
$Example.ToConfigJson()

A beállítás után $UpdateFrequency a kimenet a megadott értéket tükrözi.

{
  "unmanaged_key": true,
  "updates": {
    "automatic": false,
    "checkFrequency": 7
  }
}

A Create metódus

A Create() metódus implementálásához át kell alakítanunk a DSC-erőforrás felhasználó által megadott tulajdonságait arra a JSON-ra, amelyet a TSToy elvár a konfigurációs fájlban, és ebbe a fájlba kell írnunk.

[void] Create() {
    $ErrorActionPreference = 'Stop'

    $Json = $this.ToConfigJson()

    $FilePath   = $this.GetConfigurationFile()
    $FolderPath = Split-Path -Path $FilePath

    if (!(Test-Path -Path $FolderPath)) {
        New-Item -Path $FolderPath -ItemType Directory -Force
    }

    Set-Content -Path $FilePath -Value $Json -Encoding utf8 -Force
}

A metódus a metódust használja a ToConfigJson() konfigurációs fájl JSON-fájljának lekéréséhez. Ellenőrzi, hogy létezik-e a konfigurációs fájl mappája, és szükség esetén létrehozza azt. Végül létrehozza a konfigurációs fájlt, és beírja a JSON-t.

A Remove metódus

A Remove() metódus a legegyszerűbben viselkedik. Ha a konfigurációs fájl létezik, törölje.

[void] Remove() {
    Remove-Item -Path $this.GetConfigurationFile() -Force -ErrorAction Stop
}

Az Update metódus

A Update() metódus implementációja hasonló a Create metódushoz. Át kell alakítania a DSC-erőforrás felhasználó által megadott tulajdonságait a TSToy által a konfigurációs fájlban elvárt JSON-fájllá, és le kell cserélnie a fájlban lévő beállításokat.

[void] Update() {
    $ErrorActionPreference = 'Stop'

    $Json = $this.ToConfigJson()
    $FilePath   = $this.GetConfigurationFile()

    Set-Content -Path $FilePath -Value $Json -Encoding utf8 -Force
}

5 – DSC-erőforrás manuális tesztelése

A DSC-erőforrás teljes körű implementálásával tesztelheti a viselkedését.

A tesztelés előtt zárja be a VS Code-terminált, és nyisson meg egy újat. Pont-forrás a Helpers.ps1 szkript. Minden tesztforgatókönyvhöz hozza létre a $DesiredState megosztott paramétereket tartalmazó kivonattáblát, és hívja meg a metódusokat a következő sorrendben:

  1. Get(), a DSC-erőforrás kezdeti állapotának lekéréséhez
  2. Test(), annak megállapításához, hogy a DSC-erőforrás a kívánt állapotban van-e
  3. Set(), a kívánt állapot kényszerítéséhez
  4. Test()lehetőséget, hogy ellenőrizze, hogy a DSC-erőforrás helyesen van-e beállítva
  5. Get(), a DSC-erőforrás végleges állapotának megerősítéséhez

Forgatókönyv: A TSToy nem frissül automatikusan a felhasználói hatókörben

Ebben a forgatókönyvben a felhasználói hatókörben meglévő konfigurációt úgy kell konfigurálni, hogy ne frissüljön automatikusan. Minden más beállítást érintetlenül kell hagyni.

. ./Helpers.ps1

$DesiredState = @{
    Name     = 'Tailspin'
    Module   = 'ExampleResources'
    Property = @{
        ConfigurationScope  = 'User'
        UpdateAutomatically = $false
        Ensure              = 'Present'
    }
}

Get-Content -Path $TSToyUserPath

Invoke-DscResource @DesiredState -Method Get
Invoke-DscResource @DesiredState -Method Test
Invoke-DscResource @DesiredState -Method Set
Invoke-DscResource @DesiredState -Method Test
Invoke-DscResource @DesiredState -Method Get

Get-Content -Path $TSToyUserPath
{
    "unmanaged_key": true,
    "updates": {
        "automatic": true,
        "checkFrequency": 30
    }
}

ConfigurationScope  : User
Ensure              : Present
UpdateAutomatically : True
UpdateFrequency     : 30
Reasons             : {
                      Tailspin.Tailspin.Ensure:
                        Checked existence of the TSToy configuration file in
                      the User scope.
                        Expected configuration file to exist at 'C:\Users\mlomba
                      rdi\AppData\Roaming\TailSpinToys\tstoy\tstoy.config.json'
                      .
                        The configuration file exists at 'C:\Users\mlombardi\App
                      Data\Roaming\TailSpinToys\tstoy\tstoy.config.json'.
                      ,
                      Tailspin.Tailspin.UpdateAutomatically:
                        Checked value of the 'updates.automatic' key in the
                      TSToy configuration file.
                        Expected boolean value of 'False'
                        Actual boolean value of 'True'
                      }

InDesiredState : False

RebootRequired : False

InDesiredState : True

ConfigurationScope  : User
Ensure              : Present
UpdateAutomatically : False
UpdateFrequency     : 30
Reasons             : {
                      Tailspin.Tailspin.Ensure:
                        Checked existence of the TSToy configuration file in
                      the User scope.
                        Expected configuration file to exist at 'C:\Users\mlomba
                      rdi\AppData\Roaming\TailSpinToys\tstoy\tstoy.config.json'
                      .
                        The configuration file exists at 'C:\Users\mlombardi\App
                      Data\Roaming\TailSpinToys\tstoy\tstoy.config.json'.
                      ,
                      Tailspin.Tailspin.UpdateAutomatically:
                        Checked value of the 'updates.automatic' key in the
                      TSToy configuration file.
                        Expected boolean value of 'False'
                        Actual boolean value of 'False'
                      }

{
  "unmanaged_key": true,
  "updates": {
    "automatic": false,
    "checkFrequency": 30
  }
}

Forgatókönyv: A Tailspinnek automatikusan frissülnie kell a felhasználói hatókörben lévő ütemezés szerint

Ebben a forgatókönyvben a felhasználói hatókörben meglévő konfigurációt úgy kell konfigurálni, hogy automatikusan frissüljön. Minden más beállítást érintetlenül kell hagyni.

. ./Helpers.ps1

$DesiredState = @{
    Name     = 'Tailspin'
    Module   = 'ExampleResources'
    Property = @{
        ConfigurationScope  = 'User'
        UpdateAutomatically = $true
        Ensure              = 'Present'
    }
}

Get-Content -Path $TSToyUserPath

Invoke-DscResource @DesiredState -Method Get
Invoke-DscResource @DesiredState -Method Test
Invoke-DscResource @DesiredState -Method Set
Invoke-DscResource @DesiredState -Method Test
Invoke-DscResource @DesiredState -Method Get

Get-Content -Path $TSToyUserPath
{
  "unmanaged_key": true,
  "updates": {
    "automatic": false,
    "checkFrequency": 30
  }
}

ConfigurationScope  : User
Ensure              : Present
UpdateAutomatically : False
UpdateFrequency     : 30
Reasons             : {
                      Tailspin.Tailspin.Ensure:
                        Checked existence of the TSToy configuration file in
                      the User scope.
                        Expected configuration file to exist at 'C:\Users\mlomba
                      rdi\AppData\Roaming\TailSpinToys\tstoy\tstoy.config.json'
                      .
                        The configuration file exists at 'C:\Users\mlombardi\App
                      Data\Roaming\TailSpinToys\tstoy\tstoy.config.json'.
                      ,
                      Tailspin.Tailspin.UpdateAutomatically:
                        Checked value of the 'updates.automatic' key in the
                      TSToy configuration file.
                        Expected boolean value of 'True'
                        Actual boolean value of 'False'
                      }

InDesiredState : False

RebootRequired : False

InDesiredState : True

ConfigurationScope  : User
Ensure              : Present
UpdateAutomatically : True
UpdateFrequency     : 30
Reasons             : {
                      Tailspin.Tailspin.Ensure:
                        Checked existence of the TSToy configuration file in
                      the User scope.
                        Expected configuration file to exist at 'C:\Users\mlomba
                      rdi\AppData\Roaming\TailSpinToys\tstoy\tstoy.config.json'
                      .
                        The configuration file exists at 'C:\Users\mlombardi\App
                      Data\Roaming\TailSpinToys\tstoy\tstoy.config.json'.
                      ,
                      Tailspin.Tailspin.UpdateAutomatically:
                        Checked value of the 'updates.automatic' key in the
                      TSToy configuration file.
                        Expected boolean value of 'True'
                        Actual boolean value of 'True'
                      }

{
  "unmanaged_key": true,
  "updates": {
    "automatic": true,
    "checkFrequency": 30
  }
}

Forgatókönyv: A TSToy-nak minden nap automatikusan frissülnie kell a felhasználói hatókörben

Ebben a forgatókönyvben a felhasználói hatókörben meglévő konfigurációt úgy kell konfigurálni, hogy automatikusan és naponta frissüljön. Minden más beállítást érintetlenül kell hagyni.

. ./Helpers.ps1

$DesiredState = @{
    Name     = 'Tailspin'
    Module   = 'ExampleResources'
    Property = @{
        ConfigurationScope  = 'User'
        UpdateAutomatically = $true
        UpdateFrequency     = 1
        Ensure              = 'Present'
    }
}

Get-Content -Path $TSToyUserPath

Invoke-DscResource @DesiredState -Method Get
Invoke-DscResource @DesiredState -Method Test
Invoke-DscResource @DesiredState -Method Set
Invoke-DscResource @DesiredState -Method Test
Invoke-DscResource @DesiredState -Method Get

Get-Content -Path $TSToyUserPath
{
  "unmanaged_key": true,
  "updates": {
    "automatic": true,
    "checkFrequency": 30
  }
}

ConfigurationScope  : User
Ensure              : Present
UpdateAutomatically : True
UpdateFrequency     : 30
Reasons             : {
                      Tailspin.Tailspin.Ensure:
                        Checked existence of the TSToy configuration file in
                      the User scope.
                        Expected configuration file to exist at 'C:\Users\mlomba
                      rdi\AppData\Roaming\TailSpinToys\tstoy\tstoy.config.json'
                      .
                        The configuration file exists at 'C:\Users\mlombardi\App
                      Data\Roaming\TailSpinToys\tstoy\tstoy.config.json'.
                      ,
                      Tailspin.Tailspin.UpdateAutomatically:
                        Checked value of the 'updates.automatic' key in the
                      TSToy configuration file.
                        Expected boolean value of 'True'
                        Actual boolean value of 'True'
                      ,
                      Tailspin.Tailspin.UpdateFrequency:
                        Checked value of the 'updates.checkFrequency' key in
                      the TSToy configuration file.
                        Expected integer value of '1'.
                        Actual integer value of '30'.
                      }

InDesiredState : False

RebootRequired : False

InDesiredState : True

ConfigurationScope  : User
Ensure              : Present
UpdateAutomatically : True
UpdateFrequency     : 1
Reasons             : {
                      Tailspin.Tailspin.Ensure:
                        Checked existence of the TSToy configuration file in
                      the User scope.
                        Expected configuration file to exist at 'C:\Users\mlomba
                      rdi\AppData\Roaming\TailSpinToys\tstoy\tstoy.config.json'
                      .
                        The configuration file exists at 'C:\Users\mlombardi\App
                      Data\Roaming\TailSpinToys\tstoy\tstoy.config.json'.
                      ,
                      Tailspin.Tailspin.UpdateAutomatically:
                        Checked value of the 'updates.automatic' key in the
                      TSToy configuration file.
                        Expected boolean value of 'True'
                        Actual boolean value of 'True'
                      ,
                      Tailspin.Tailspin.UpdateFrequency:
                        Checked value of the 'updates.checkFrequency' key in
                      the TSToy configuration file.
                        Expected integer value of '1'.
                        Actual integer value of '1'.
                      }

{
  "unmanaged_key": true,
  "updates": {
    "checkFrequency": 1,
    "automatic": true
  }
}

Forgatókönyv: A TSToy nem rendelkezhet felhasználói hatókör-konfigurációval

Ebben a forgatókönyvben a felhasználói hatókörben lévő TSToy konfigurációs fájljának nem kell léteznie. Ha igen, a DSC-erőforrásnak törölnie kell a fájlt.

. ./Helpers.ps1

$DesiredState = @{
    Name     = 'Tailspin'
    Module   = 'ExampleResources'
    Property = @{
        ConfigurationScope  = 'User'
        UpdateAutomatically = $false
        Ensure              = 'Absent'
    }
}

Get-Content -Path $TSToyUserPath

Invoke-DscResource @DesiredState -Method Get
Invoke-DscResource @DesiredState -Method Test
Invoke-DscResource @DesiredState -Method Set
Invoke-DscResource @DesiredState -Method Test
Invoke-DscResource @DesiredState -Method Get

Test-Path -Path $TSToyUserPath
{
  "unmanaged_key": true,
  "updates": {
    "checkFrequency": 1,
    "automatic": true
  }
}

ConfigurationScope  : User
Ensure              : Present
UpdateAutomatically : True
UpdateFrequency     : 1
Reasons             : {
                      Tailspin.Tailspin.Ensure:
                        Checked existence of the TSToy configuration file in
                      the User scope.
                        Expected configuration file not to exist at 'C:\Users\ml
                      ombardi\AppData\Roaming\TailSpinToys\tstoy\tstoy.config.j
                      son'.
                        The configuration file exists at 'C:\Users\mlombardi\App
                      Data\Roaming\TailSpinToys\tstoy\tstoy.config.json'.
                      }

InDesiredState : False

RebootRequired : False

InDesiredState : True

ConfigurationScope  : User
Ensure              : Absent
UpdateAutomatically : False
UpdateFrequency     : 0
Reasons             : {
                      Tailspin.Tailspin.Ensure:
                        Checked existence of the TSToy configuration file in
                      the User scope.
                        Expected configuration file not to exist at 'C:\Users\ml
                      ombardi\AppData\Roaming\TailSpinToys\tstoy\tstoy.config.j
                      son'.
                        The configuration file was not found at 'C:\Users\mlomba
                      rdi\AppData\Roaming\TailSpinToys\tstoy\tstoy.config.json'
                      .
                      }

False

Forgatókönyv: A TSToy-nak hetente automatikusan frissítenie kell a gép hatókörében

Ebben a forgatókönyvben nincs definiált konfiguráció a gép hatókörében. A gép hatókörét úgy kell konfigurálni, hogy automatikusan és naponta frissüljön. A DSC-erőforrásnak szükség szerint létre kell hoznia a fájlt és a szülőmappákat.

. ./Helpers.ps1

$DesiredState = @{
    Name     = 'Tailspin'
    Module   = 'ExampleResources'
    Property = @{
        ConfigurationScope  = 'Machine'
        UpdateAutomatically = $true
        Ensure              = 'Present'
    }
}

Test-Path -Path $TSToyMachinePath, (Split-Path -Path $TSToyMachinePath)

Invoke-DscResource @DesiredState -Method Get
Invoke-DscResource @DesiredState -Method Test
Invoke-DscResource @DesiredState -Method Set
Invoke-DscResource @DesiredState -Method Test
Invoke-DscResource @DesiredState -Method Get

Get-Content -Path $TSToyMachinePath
False
False

ConfigurationScope  : Machine
Ensure              : Absent
UpdateAutomatically : False
UpdateFrequency     : 0
Reasons             : {
                      Tailspin.Tailspin.Ensure:
                        Checked existence of the TSToy configuration file in
                      the Machine scope.
                        Expected configuration file to exist at
                      'C:\ProgramData\TailSpinToys\tstoy\tstoy.config.json'.
                        The configuration file was not found at
                      'C:\ProgramData\TailSpinToys\tstoy\tstoy.config.json'.
                      }

InDesiredState : False

RebootRequired : False

InDesiredState : True

ConfigurationScope  : Machine
Ensure              : Present
UpdateAutomatically : True
UpdateFrequency     : 0
Reasons             : {
                      Tailspin.Tailspin.Ensure:
                        Checked existence of the TSToy configuration file in
                      the Machine scope.
                        Expected configuration file to exist at
                      'C:\ProgramData\TailSpinToys\tstoy\tstoy.config.json'.
                        The configuration file exists at
                      'C:\ProgramData\TailSpinToys\tstoy\tstoy.config.json'.
                      ,
                      Tailspin.Tailspin.UpdateAutomatically:
                        Checked value of the 'updates.automatic' key in the
                      TSToy configuration file.
                        Expected boolean value of 'True'
                        Actual boolean value of 'True'
                      }

{
  "updates": {
    "automatic": true
  }
}

Áttekintés

Az oktatóanyag során az alábbi lépéseket fogja végrehajtani:

  1. Egy PowerShell-modul létrehozása és az Tailspin osztályalapú DSC-erőforrás implementálása
  2. Definiálta a DSC-erőforrás tulajdonságait a TSToy-alkalmazás frissítési viselkedésének kezeléséhez a gépen és a felhasználói hatókörökben ezen tulajdonságok ellenőrzésével
  3. A és $ConfigurationScope a $Ensure tulajdonsághoz implementált enumerálások
  4. Implementálta a ExampleResourcesReason osztályt, amely azt jelenti, hogy egy erőforrás nincs állapotban a gép konfigurációjában
  5. Implementálta a GetConfigurationFile() segédmetódust, amellyel megbízhatóan felderíthetők a TSToy alkalmazáskonfigurálásának helye a gépen és a felhasználói hatókörökben a különböző platformokon
  6. Implementálta a metódust Get() a DSC-erőforrás aktuális állapotának lekéréséhez, gyorsítótárazva a és Set() a Test() metódusban való használathoz
  7. Implementálta a GetReasons() segédmetódust annak ellenőrzésére, hogy a DSC-erőforrás a kívánt állapotban van-e, és ha nem, akkor az állapoton kívüli állapotának felsorolása
  8. Implementálta a Test() TSToy frissítési viselkedésének aktuális állapotának ellenőrzésére szolgáló metódust egy adott hatókörben a kívánt állapothoz
  9. Implementálta a ToConfigJson metódust a DSC-erőforrás kívánt állapotának átalakításához a TSToy-alkalmazás által a konfigurációs fájlhoz szükséges JSON-objektummá, figyelembe véve a nem felügyelt beállításokat
  10. Implementálta a metódust és a Set()Create, Remove és Update segédmetódust, hogy idempotens módon kényszerítse ki a kívánt állapotot a TSToy frissítési viselkedéséhez egy adott hatókörben, biztosítva, hogy a DSC-erőforrásnak ne legyenek nemkívánatos mellékhatásai
  11. A DSC-erőforrás gyakori használati forgatókönyveinek manuális tesztelése

Az implementáció végén a moduldefiníció a következőképpen néz ki:

[DscResource()]
class Tailspin {
    [DscProperty(Key)] [TailspinScope]
    $ConfigurationScope

    [DscProperty()] [TailspinEnsure]
    $Ensure = [TailspinEnsure]::Present

    [DscProperty(Mandatory)] [bool]
    $UpdateAutomatically

    [DscProperty()] [int] [ValidateRange(1, 90)]
    $UpdateFrequency

    [DscProperty(NotConfigurable)] [ExampleResourcesReason[]]
    $Reasons

    hidden [Tailspin] $CachedCurrentState
    hidden [PSCustomObject] $CachedData

    [Tailspin] Get() {
        $CurrentState = [Tailspin]::new()

        $CurrentState.ConfigurationScope = $this.ConfigurationScope

        $FilePath = $this.GetConfigurationFile()

        if (!(Test-Path -Path $FilePath)) {
            $CurrentState.Ensure = [TailspinEnsure]::Absent
            $CurrentState.Reasons = $this.GetReasons($CurrentState)

            $this.CachedCurrentState = $CurrentState

            return $CurrentState
        }

        $Data = Get-Content -Raw -Path $FilePath |
        ConvertFrom-Json -ErrorAction Stop

        $this.CachedData = $Data

        if ($null -ne $Data.Updates.Automatic) {
            $CurrentState.UpdateAutomatically = $Data.Updates.Automatic
        }

        if ($null -ne $Data.Updates.CheckFrequency) {
            $CurrentState.UpdateFrequency = $Data.Updates.CheckFrequency
        }

        $CurrentState.Reasons = $this.GetReasons($CurrentState)

        $this.CachedCurrentState = $CurrentState

        return $CurrentState
    }

    [bool] Test() {
        $CurrentState = $this.Get()

        if ($CurrentState.Ensure -ne $this.Ensure) {
            return $false
        }

        if ($CurrentState.UpdateAutomatically -ne $this.UpdateAutomatically) {
            return $false
        }

        if ($this.UpdateFrequency -eq 0) {
            return $true
        }

        if ($CurrentState.UpdateFrequency -ne $this.UpdateFrequency) {
            return $false
        }

        return $true
    }

    [void] Set() {
        if ($this.Test()) {
            return
        }

        $CurrentState = $this.CachedCurrentState

        $IsAbsent = $CurrentState.Ensure -eq [TailspinEnsure]::Absent
        $ShouldBeAbsent = $this.Ensure -eq [TailspinEnsure]::Absent

        if ($IsAbsent) {
            $this.Create()
        }
        elseif ($ShouldBeAbsent) {
            $this.Remove()
        }
        else {
            $this.Update()
        }
    }

    [string] GetConfigurationFile() {
        $FilePaths = @{
            Linux   = @{
                Machine = '/etc/xdg/TailSpinToys/tstoy/tstoy.config.json'
                User    = '~/.config/TailSpinToys/tstoy/tstoy.config.json'
            }
            MacOS   = @{
                Machine = '/Library/Preferences/TailSpinToys/tstoy/tstoy.config.json'
                User    = '~/Library/Preferences/TailSpinToys/tstoy/tstoy.config.json'
            }
            Windows = @{
                Machine = "$env:ProgramData\TailSpinToys\tstoy\tstoy.config.json"
                User    = "$env:APPDATA\TailSpinToys\tstoy\tstoy.config.json"
            }
        }

        $Scope = $this.ConfigurationScope.ToString()

        if ($Global:PSVersionTable.PSVersion.Major -lt 6 -or $Global:IsWindows) {
            return $FilePaths.Windows.$Scope
        }
        elseif ($Global:IsLinux) {
            return $FilePaths.Linux.$Scope
        }
        else {
            return $FilePaths.MacOS.$Scope
        }
    }

    [ExampleResourcesReason[]] GetReasons([Tailspin]$CurrentState) {
        [ExampleResourcesReason[]]$DefinedReasons = @()

        $FilePath = $this.GetConfigurationFile()

        if ($this.Ensure -eq [TailspinEnsure]::Present) {
            $Expected = "Expected configuration file to exist at '$FilePath'."
        } else {
            $Expected = "Expected configuration file not to exist at '$FilePath'."
        }

        if ($CurrentState.Ensure -eq [TailspinEnsure]::Present) {
            $Actual = "The configuration file exists at '$FilePath'."
        } else {
            $Actual = "The configuration file was not found at '$FilePath'."
        }

        $DefinedReasons += [ExampleResourcesReason]@{
            Code   = "Tailspin.Tailspin.Ensure"
            Phrase = @(
                "Checked existence of the TSToy configuration file in the $($this.ConfigurationScope) scope."
                $Expected
                $Actual
            ) -join "`n`t"
        }

        if ($CurrentState.Ensure -ne $this.Ensure) {
            return $DefinedReasons
        }

        if ($CurrentState.Ensure -eq [TailspinEnsure]::Absent) {
            return $DefinedReasons
        }

        $DefinedReasons += [ExampleResourcesReason]@{
            Code   = "Tailspin.Tailspin.UpdateAutomatically"
            Phrase = (@(
                    "Checked value of the 'updates.automatic' key in the TSToy configuration file."
                    "Expected boolean value of '$($this.UpdateAutomatically)'"
                    "Actual boolean value of '$($CurrentState.UpdateAutomatically)'"
                ) -join "`n`t")
        }

        # Short-circuit the check; UpdateFrequency isn't defined by caller
        if ($this.UpdateFrequency -eq 0) {
            return $DefinedReasons
        }

        $DefinedReasons += [ExampleResourcesReason]@{
            Code   = "Tailspin.Tailspin.UpdateFrequency"
            Phrase = (@(
                    "Checked value of the 'updates.checkFrequency' key in the TSToy configuration file."
                    "Expected integer value of '$($this.UpdateFrequency)'."
                    "Actual integer value of '$($CurrentState.UpdateFrequency)'."
                ) -join "`n`t")
        }

        return $DefinedReasons
    }

    [void] Create() {
        $ErrorActionPreference = 'Stop'

        $Json = $this.ToConfigJson()

        $FilePath = $this.GetConfigurationFile()

        $FolderPath = Split-Path -Path $FilePath

        if (!(Test-Path -Path $FolderPath)) {
            New-Item -Path $FolderPath -ItemType Directory -Force
        }

        Set-Content -Path $FilePath -Value $Json -Encoding utf8 -Force
    }

    [void] Remove() {
        Remove-Item -Path $this.GetConfigurationFile() -Force -ErrorAction Stop
    }

    [void] Update() {
        $ErrorActionPreference = 'Stop'

        $Json = $this.ToConfigJson()
        $FilePath = $this.GetConfigurationFile()

        Set-Content -Path $FilePath -Value $Json -Encoding utf8 -Force
    }

    [string] ToConfigJson() {
        $config = @{
            updates = @{
                automatic = $this.UpdateAutomatically
            }
        }

        if ($this.CachedData) {
            $this.CachedData |
                Get-Member -MemberType NoteProperty |
                Where-Object -Property Name -NE -Value 'updates' |
                ForEach-Object -Process {
                    $setting = $_.Name
                    $config.$setting = $this.CachedData.$setting
                }

            if ($frequency = $this.CachedData.updates.CheckFrequency) {
                $config.updates.checkFrequency = $frequency
            }
        }

        if ($this.UpdateFrequency -ne 0) {
            $config.updates.checkFrequency = $this.UpdateFrequency
        }

        return ($config | ConvertTo-Json)
    }
}

enum TailspinScope {
    Machine
    User
}

enum TailspinEnsure {
    Absent
    Present
}

class ExampleResourcesReason {
    [DscProperty()]
    [string] $Code

    [DscProperty()]
    [string] $Phrase

    [string] ToString() {
        return "`n$($this.Code):`n`t$($this.Phrase)`n"
    }
}

A fölöslegessé vált elemek eltávolítása

Ha nem fogja tovább használni ezt a modult, törölje a ExampleResources mappát és a benne lévő fájlokat.

Következő lépések

  1. Olvassa el az osztályalapú DSC-erőforrásokat, ismerje meg azok működését, és gondolja át, hogy az oktatóanyagban miért implementáljuk így a DSC-erőforrást.
  2. Olvassa el az Azure Automanage gépkonfigurációs funkcióját , amelyből megtudhatja, hogyan használhatja a rendszerek naplózására és konfigurálására.
  3. Gondolja át, hogyan javítható ez a DSC-erőforrás. Vannak olyan peremhálózati esetek vagy funkciók, amelyeket nem kezel? Frissítse az implementációt a kezelésükhöz.