Udostępnij za pośrednictwem


Zasoby DSC oparte na klasach

Zasoby DSC oparte na klasach zapewniają uproszczoną implementację zasobów DSC do zarządzania ustawieniami systemu. W tym artykule wyjaśniono ich strukturę i wymagania.

Struktura zasobu DSC opartego na klasach

Zasób DSC oparty na klasie jest definiowany jako klasa programu PowerShell w pliku modułu (.psm1). Zasób DSC oparty na klasach nie ma specjalnych wymagań dotyczących tego, gdzie jest zdefiniowany. Można go zdefiniować:

Niezależnie od tego, gdzie jest zdefiniowany zasób DSC, zasób DSC musi być wymieniony we właściwości DscResourcesToExport pliku manifestu modułu (.psd1). Polecenie cmdlet Get-DscResource , dynamiczne słowo kluczowe [Import-DSCResource] i samo rozszerzenie DSC podczas kompilowania konfiguracji DSC zakończy się niepowodzeniem, jeśli zasób DSC nie znajduje się na liście manifestu.

Aby uzyskać więcej informacji na temat tworzenia manifestu modułu, zobacz New-ModuleManifest. Aby uzyskać więcej informacji na temat ustawień manifestu modułu, zobacz about_Module_Manifests.

Zasób DSC oparty na klasach musi:

  1. Użyj atrybutu DscResource .
  2. Zadeklaruj co najmniej jedną właściwość za pomocą atrybutu DscProperty . Co najmniej jedna z właściwości musi być właściwością Key .
  3. Zaimplementuj Get()metody , Test()i Set() .
  4. Zdefiniuj konstruktor domyślny, jeśli definiuje jakiekolwiek alternatywne konstruktory.

Atrybut DscResource

Definicja klasy musi mieć atrybut DscResource . Ten atrybut wskazuje, że klasa definiuje zasób DSC.

Aby dodać atrybut DscResource do klasy, zadeklaruj go w wierszu bezpośrednio przed definicją klasy.

[DscResource()]
class MyDscResource {
}

Oprócz identyfikowania klasy jako zasobu DSC atrybut DscResource stosuje weryfikację analizy czasu do zasobu DSC opartego na klasie. Program PowerShell zgłasza błąd analizy definicji zasobu DSC opartego na klasach, gdy:

  • Co najmniej jedna z Get()metod , Test()i Set() jest niepoprawnie zdefiniowana lub brakuje
  • Klasa nie ma co najmniej jednej właściwości Klucz
  • Klasa definiuje konstruktor inny niż domyślny bez definiowania konstruktora domyślnego

Atrybut DscResource można również określić za pomocą właściwości RunAsCredential , aby określić zachowanie zasobu DSC opartego na klasie podczas korzystania z właściwości PsDscRunAsCredential :

  • Optional — Użytkownik może użyć właściwości PsDscRunAsCredential z tym zasobem DSC. Jest to zachowanie domyślne. To zachowanie można również określić jako Default zamiast Optional.
  • NotSupported — Użytkownik nie może użyć właściwości PsDscRunAsCredential z tym zasobem DSC.
  • Mandatory — Użytkownik musi użyć właściwości PsDscRunAsCredential z tym zasobem DSC.

Uwaga

Można ustawić właściwość RunAsCredential dla zasobu DSC opartego na klasie, ale nie ma żadnego wpływu w przypadku korzystania z rozszerzenia DSC w wersji 2.0 lub nowszej. Właściwość PsDscRunAsCredential jest obsługiwana tylko w wersji DSC w wersji 1.1 i starszych. Jeśli piszesz zasób DSC oparty na klasie i obsługujesz go w wersji DSC w wersji 1.1, określenie tej właściwości w atrybucie DscResource zapewnia pewną przejrzystość i ulepszone środowisko użytkownika dla tego scenariusza.

Właściwości zasobu DSC oparte na klasach

Schemat zasobu DSC opartego na klasie jest definiowany przez właściwości klasy. Aby właściwość została rozpoznana jako część schematu, musi mieć atrybut DscProperty .

Definicja właściwości DscProperty określa sposób traktowania tej właściwości przez rozszerzenie DSC:

  • [DscProperty(Key)] — Wskazuje, że ta właściwość jednoznacznie identyfikuje wystąpienie tego zasobu DSC. Każdy zasób DSC musi mieć co najmniej jedną właściwość Klucz . Jeśli zasób DSC ma więcej niż jedną właściwość Klucz , te właściwości są używane razem do unikatowego identyfikowania wystąpienia zasobu DSC. Jeśli jakiekolwiek właściwości klucza zasobu DSC nie są określone podczas korzystania z Invoke-DscResourcepolecenia , polecenie cmdlet zgłasza błąd. Jeśli podczas tworzenia konfiguracji DSC nie określono żadnych właściwości klucza , kompilowanie konfiguracji powoduje wystąpienie błędu.
  • [DscProperty(Mandatory)] — Wskazuje, że właściwość musi być określona podczas korzystania z tego zasobu DSC. Jeśli podczas korzystania z usługi Invoke-DscResourcenie określono żadnych obowiązkowych właściwości zasobu DSC, polecenie cmdlet zgłasza błąd. Jeśli podczas tworzenia konfiguracji DSC nie określono żadnych obowiązkowych właściwości, kompilowanie konfiguracji powoduje wystąpienie błędu.
  • [DscProperty(NotConfigurable)] - Wskazuje, że właściwość jest ReadOnly. Nie jest to możliwe do zarządzania ustawienie tego zasobu DSC, ale będzie zawierać wartość po wywołaniu Get() metody zasobu DSC.
  • [DscProperty()] — Wskazuje, że właściwość jest konfigurowalnym ustawieniem tego zasobu DSC. Określenie tej właściwości jest opcjonalne podczas używania Invoke-DscResource lub tworzenia konfiguracji DSC.

Podobnie jak we wszystkich właściwościach klasy programu PowerShell, właściwości zasobu DSC opartego na klasach muszą określać typ. Ten typ służy do sprawdzania poprawności określonego ustawienia podczas wywoływania Invoke-DscResource lub kompilowania konfiguracji DSC.

Rozważmy ten fragment definicji zasobu DSC opartego na MyDscResource klasie:

[DscResource()]
class MyDscResource {
    [DscProperty(Key)]
    [string] $Path

    [DscProperty(Mandatory)]
    [hashtable]$Settings

    [DscProperty(NotConfigurable)]
    [datetime] $LastModified

    [DscProperty()]
    [string] $Format = 'YAML'
}

Definiuje cztery właściwości:

  • Ścieżka jest właściwością Key dla zasobu DSC i oczekuje pobrania ciągu dla jego wartości.
  • Ustawienia to właściwość Obowiązkowa dla zasobu DSC i oczekuje, że dla jej wartości zostanie pobrana tabela skrótów .
  • LastModified jest właściwością ReadOnly dla zasobu DSC i oczekuje pobrania wartości DateTime dla jej wartości z Get() metody .
  • Format jest opcjonalną właściwością zasobu DSC i oczekuje pobrania ciągu dla jego wartości.

Domyślne wartości właściwości

Po utworzeniu wystąpienia zasobu DSC opartego na klasie jest używany domyślny konstruktor bez parametrów. Jeśli to zachowanie nie zostanie zastąpione, domyślny konstruktor bez parametrów inicjuje każdą właściwość do wartości domyślnej dla jego typu. Jeśli właściwość jest zdefiniowana z jawną wartością domyślną, ta wartość jest używana zamiast tego. Aby uzyskać więcej informacji na temat konstruktorów dla zasobów DSC opartych na klasach, zobacz Konstruktory.

Określa, czy właściwość jest typem referencyjnym , czy typem wartości domyślnej. Typy odwołań inicjują wartość $null. Typy wartości inicjują wartość określoną w ich definicji.

W przeciwieństwie do innych implementacji zasoby DSC oparte na klasach zarządzają wszystkimi zdefiniowanymi właściwościami, które mają atrybut DscProperty , nawet jeśli nie określisz tej właściwości w konfiguracji DSC lub w przypadku używania polecenia Invoke-DscResource. Ponieważ właściwości typu wartości mają wartość domyślną inną niż null, nie ma możliwości, aby zasób DSC oparty na klasie rozróżniał właściwość, która nie została określona i która została określona jako wartość domyślna.

Ważne

Jeśli używasz zasobu DSC opartego na klasie, wszystkie właściwości typu wartości, które nie są jawnie ustawione, są zawsze ustawiane na ich wartość domyślną zgodnie z definicją w zasobie DSC.

Nie można użyć zasobu DSC opartego na klasach bez zarządzania każdą właściwością typu wartości zdefiniowaną dla tego zasobu DSC. W przeciwieństwie do innych zasobów DSC usunięcie właściwości z konfiguracji DSC lub wywołanie Invoke-DscResource metody nie powoduje zignorowania stanu tej właściwości. Spowoduje to zresetowanie go do wartości domyślnej.

Tylko właściwości typu odwołania mogą być niezarządzane dla zasobu DSC opartego na klasie.

Możesz sprawdzić, czy typ jest odwołaniem, czy typem wartości, sprawdzając jego typ BaseType.

function Test-IsValueType ($Object) {
    $base = $Object.GetType().BaseType
    while ($true) {
        switch ($base.FullName) {
            'System.Object' { return $false }
            'System.ValueType' { return $true }
            default {
                $base = $base.BaseType
            }
        }
    }
}

Test-IsValueType 'foo'
Test-IsValueType 5
False
True

Ta tabela zawiera kilka typów często używanych w zasobach DSC. Zwraca uwagę, czy są to typy odwołań, czy wartości, a jeśli są typami wartości, to jaka jest ich wartość domyślna, gdy zasób DSC jest inicjowany.

Nazwa Typ Wartość domyślna
System.enum Wartość 0
System.Int32 Wartość 0
System.double Wartość 0
System.datetime Wartość 1 stycznia 0001 12:00:00
System.timespan Wartość Wszystkie pola ustawione na 0wartość .
System.string Odwołanie $null
System.Management.Automation.PSCredential Odwołanie $null

Atrybuty właściwości weryfikacji

Właściwości zasobu DSC opartego na klasie mogą również używać atrybutów weryfikacji , aby ograniczyć wartości określone przez użytkownika dla właściwości. Walidacja jest stosowana podczas kompilowania konfiguracji DSC lub wywołania metody Invoke-DSCResource. Program VS Code nie weryfikuje wartości określonych w konfiguracji DSC podczas edytowania.

Przestroga

W przypadku używania Invoke-DscResourcemetody błędy walidacji właściwości nie zatrzymują polecenia cmdlet podczas wywoływania Get()metody , Test()lub Set() . Aby zapobiec wywołaniu metody w przypadku niepowodzenia atrybutu weryfikacji właściwości przez polecenie cmdlet, określ wartość ErrorActionPreference jako Stop.

Definiowanie atrybutów weryfikacji dla właściwości jest prostsze niż implementacja tej samej logiki w metodzie i jest wykrywalne metadane dotyczące klasy definiującej zasób DSC. Jeśli to możliwe, lepiej jest jawnie poznać wartości, które akceptują właściwości zasobu DSC. Wyjaśnia to użycie i zapewnia bezpieczniejsze i bardziej niezawodne środowisko.

Rozważmy ten fragment definicji zasobu DSC opartego MyDscResource na klasie:

[DscResource()]
class MyDscResource {
    [DscProperty()]
    [string]
    [ValidateSet('JSON', 'YAML')]
    $Format
}

Używa atrybutu ValidateSet , aby ograniczyć prawidłowe wartości właściwości Format do JSON i YAML. Jeśli używasz Invoke-DscResource z nieprawidłową wartością formatu, błędy polecenia cmdlet:

$Parameters = @{
    Name       = 'MyDscResource'
    ModuleName = 'MyDscResources'
    Method     = 'Get'
    Property   = @{
        Path     = '/Dsc/Example/config.yaml'
        Format   = 'Incorrect'
        Settings = @{
            Foo = 'Bar'
        }
    }
}
Invoke-DscResource @Parameters -ErrorAction Stop
Invoke-DscClassBasedResource: Exception setting "Format": "The argument
"Incorrect" does not belong to the set "YAML,JSON" specified by the
ValidateSet attribute. Supply an argument that is in the set and then
try the command again."

Aby uzyskać więcej informacji na temat atrybutów weryfikacji, zobacz about_Functions_Advanced_Parameters.

Właściwości wyliczenia

Aby uzyskać lepsze środowisko tworzenia i obsługi użytkownika niż za pomocą atrybutu ValidateSet, można zdefiniować wyliczenie, które określa zestaw prawidłowych wartości.

Można na przykład zdefiniować wyliczenie FormatOption i użyć go jako typu właściwości Format zasobu DSC opartego na klasie:

enum FormatOption {
    JSON
    YAML
}

[DscResource()]
class MyDscResource {
    [DscProperty()]
    [FormatOption]
    $Format
}

Komunikat o błędzie nieprawidłowej wartości wyliczenia jest krótszy i jaśniejszy niż w przypadku elementu ValidateSet:

$Parameters = @{
    Name       = 'MyDscResource'
    ModuleName = 'MyDscResources'
    Method     = 'Get'
    Property   = @{
        Path     = '/Dsc/Example/config.yaml'
        Format   = 'Incorrect'
        Settings = @{}
    }
}
Invoke-DscResource @Parameters -ErrorAction Stop
Invoke-DscClassBasedResource: Exception setting "Format": "Cannot
convert value "Incorrect" to type "FormatOption". Error: "Unable to
match the identifier name Incorrect to a valid enumerator name. Specify
one of the following enumerator names and try again: JSON, YAML""

Wyliczenia są również przydatne w przypadku, gdy trzeba użyć tej samej właściwości w kilku zasobach DSC opartych na klasach. Możesz zdefiniować wyliczenie raz i użyć go wszędzie, natomiast za pomocą atrybutu ValidateSet należy zaktualizować każdy zasób DSC, który współudzieli właściwość.

Aby uzyskać więcej informacji na temat wyliczenia w programie PowerShell, zobacz about_Enum.

Właściwość Ensure

Wiele zasobów DSC ma właściwość Ensure , która kontroluje stan wystąpienia zasobu DSC. Na przykład zasób DSC w module PSDscResources ma właściwość Upewnij się, User że przyjmuje wartości Present (wskazujące, że użytkownik powinien istnieć) i Absent (wskazując, że użytkownik nie powinien istnieć).

W przypadku zasobów DSC opartych na klasach sugerowaną praktyką jest utworzenie wyliczenie i użycie go dla dowolnych zasobów DSC z możliwością zapewnienia zgodności jako typu właściwości o nazwie Ensure. Na przykład:

enum Ensure {
    Absent
    Present
}

[DscResource()]
class MyDscResource {
    [DscProperty()]
    [Ensure]
    $Ensure
}

Chociaż jest to typowe dla wyliczenia Upewnij się, że definiuje wartości Absent i Present, może zdefiniować dowolne wartości, które mają sens dla zasobu DSC.

Korzystając z przykładowego zasobu DSC tego artykułu SimpleConfig , zamiast tylko mieć Absent (plik konfiguracji nie powinien istnieć) i Present, można zdefiniować opcję Upewnij się , że mają następujące wartości:

  • Absent — Konfiguracja nie powinna istnieć w określonej ścieżce. Jeśli tak, zasób DSC powinien usunąć go z systemu.
  • Exactly — Konfiguracja powinna istnieć w określonej ścieżce z ustawieniami zdefiniowanymi tylko w właściwości Ustawienia . Jeśli jakiekolwiek ustawienia mają nieprawidłową wartość, zasób DSC powinien je poprawić. Jeśli plik konfiguracji nie ma żadnych ustawień określonych we właściwości Ustawienia , powinien je usunąć.
  • Include — Konfiguracja powinna istnieć w określonej ścieżce z ustawieniami zdefiniowanymi we właściwości Ustawienia . Jeśli jakiekolwiek ustawienia mają nieprawidłową wartość, zasób DSC powinien je poprawić. Jeśli plik konfiguracji ma jakiekolwiek ustawienia, które nie zostały określone we właściwości Ustawienia , powinien je zignorować.
  • Present - Konfiguracja powinna istnieć w określonej ścieżce. Jeśli tak nie jest, zasób DSC powinien utworzyć go z ustawieniami zdefiniowanymi we właściwości Ustawienia . Jeśli tak się stanie, zasób DSC powinien zgłosić wystąpienie jako w żądanym stanie, nawet jeśli ustawienia nie są zgodne z tymi określonymi we właściwości Ustawienia .

To wyliczenie można zdefiniować w następujący sposób:

enum Ensure {
    Absent
    Exactly
    Include
    Present
}

Właściwości złożone

Niektóre właściwości zasobu DSC mogą mieć podwłaściwości. Na przykład właściwość Ustawienia zasobu DSC tego artykułu SimpleConfig została określona wcześniej w tym artykule z typem tabela skrótu . Umożliwia to użytkownikowi określenie dowolnych nazw kluczy i dowolnych typów wartości dla każdego klucza.

Zamiast tego, aby kontrolować prawidłowe opcje, można napisać klasę reprezentującą właściwość złożoną. Aby właściwości tej klasy były rozpoznawane przez DSC jako podwłaściwości, muszą mieć atrybut DscProperty .

class SimpleConfigSettings {
    [DscProperty()] [string]
    $ProfileName

    [DscProperty()] [string]
    $Description

    [DscProperty()] [int]
    [ValidateRange(0,90)]
    $CheckForUpdates
}

Klasa SimpleConfigSettings definiuje trzy ustawienia: ProfileName jako ciąg, Opis jako ciąg i CheckForUpdates jako int , którego wartość musi należeć do zakresu od 0 do 90.

Uwaga

Mimo że właściwości złożone są definiowane jako klasy, a ich podwłaściwości muszą mieć atrybut DscProperty , atrybut właściwości w zasobie DSC jest jedynym, który stosuje wszelkie zmiany behawioralne do właściwości. Oznaczanie podwłaściwości jako Klucz, Obowiązkowe lub Niekonfigurowalne nie ma wpływu na zachowanie kontrolera DSC podczas kompilowania konfiguracji DSC lub używania polecenia Invoke-DscResource.

W przypadku zdefiniowanej klasy można jej użyć jako właściwości zasobu DSC:

[DscResource()]
class SimpleConfig {
    [DscProperty(Mandatory)] [SimpleConfigSettings]
    $Settings
}

W przypadku ustawienia zdefiniowanego jako typ SimpleConfigSettings użytkownicy uzyskują jasne informacje o wartości, którą muszą podać.

$Parameters = @{
    Name       = 'MyDscResource'
    ModuleName = 'MyDscResources'
    Method     = 'Get'
    Property   = @{
        Path   = '/Dsc/Example/config.yaml'
        Format = 'YAML'
        Settings  = @{ Name = 'Foo' }
    }
}

Invoke-DscResource @Parameters -ErrorAction Stop
Invoke-DscClassBasedResource: Exception setting "Settings": "Cannot
create object of type "SimpleConfigSettings". The Name property was not
found for the SimpleConfigSettings object. The available property is:
[ProfileName <System.String>] , [Description <System.String>] ,
[CheckForUpdates <System.Int32>]"

Właściwości złożone mogą mieć również właściwości złożone. Nie ma żadnego ograniczenia do poziomu zagnieżdżania, którego można użyć. Aby uzyskać najlepsze środowisko użytkownika, ogranicz głębokość złożonych właściwości do trzech poziomów.

class SimpleConfigUpdateSettings {
    [DscProperty()] [int]
    [ValidateRange(0,90)]
    $Interval

    [DscProperty()] [string]
    $Url
}

class SimpleConfigSettings {
    [DscProperty()] [string]
    $ProfileName

    [DscProperty()] [string]
    $Description

    [DscProperty()] [SimpleConfigUpdateSettings]
    $Updates
}

[DscResource()]
class SimpleConfig {
    [DscProperty(Mandatory)] [SimpleConfigSettings]
    $Settings
}

W tym przykładzie pokazano, jak definiowanie zagnieżdżonych złożonych właściwości zapewnia walidację. Ta walidacja zapewnia przydatne komunikaty o błędach podczas wywoływania metody Invoke-DscResource.

$Parameters = @{
    Name       = 'MyDscResource'
    ModuleName = 'MyDscResources'
    Method     = 'Get'
    Property   = @{
        Path     = '/Dsc/Example/config.yaml'
        Format   = 'YAML'
        Settings = @{
            ProfileName = 'Foo'
            Updates = @{
                Interval = 30
                Oops = 'Invalid property'
            }
        }
    }
}

Invoke-DscResource @Parameters -ErrorAction Stop
Invoke-DscClassBasedResource: Exception setting "Settings": "Cannot
create object of type "SimpleConfigSettings". Cannot create object of
type "SimpleConfigUpdateSettings". The Interval property was not found
for the SimpleConfigUpdateSettings object. The available property is:
[UpdateInterval <System.Int32>] , [UpdateUrl <System.String>]"

Właściwość Reasons

Jeśli zasób DSC oparty na klasie jest przeznaczony do użycia z funkcją konfiguracji maszyny usługi Azure Automanage, zasób DSC musi mieć właściwość Reasons , która spełnia następujące wymagania:

  • Musi on zostać zadeklarowany za pomocą właściwości NotConfigurable w atrybucie DscProperty .
  • Musi to być tablica obiektów, które mają właściwość String o nazwie Code, właściwość String o nazwie Phrase i nie ma innych właściwości. Typ obiektu można zdefiniować jako tabelę skrótów lub utworzyć obiekt jako właściwość złożoną.

Konfiguracja maszyny używa właściwości Reasons , aby ustandaryzować sposób prezentowania informacji o zgodności. Każdy obiekt zwrócony przez metodę Get() właściwości Reasons określa, jak i dlaczego wystąpienie zasobu DSC nie jest zgodne.

Konfiguracja maszyny oczekuje właściwości Kod i Fraza . Właściwość Fraza powinna być ciągiem czytelnym dla człowieka, który wyjaśnia, jak wystąpienie jest poza żądanym stanem. Właściwość Code musi być sformatowana specjalnie, aby konfiguracja komputera mogła wyraźnie wyświetlać informacje o inspekcji zasobu DSC.

Właściwość Code używa tego formatowania bez spacji:

<ResourceName>:<ResourceName>:<Identifier>

W tym formatowaniu zastąp <ResourceName> wartość rzeczywistą nazwą zasobu DSC i <Identifier> krótką nazwą, dlaczego zasób DSC jest nieaktualny. Właściwość Code nie może zawierać żadnych znaków odstępów. Jeśli na przykład zasób DSC o nazwie Tailspin nie był zgodny, ponieważ plik konfiguracji nie istnieje, kod może być Tailspin:Tailspin:ConfigFileNotFound.

W tym fragmencie kodu pokazano, jak można zdefiniować właściwość Reasons jako tabelę skrótów:

class MyDscResource {
    [DscProperty(NotConfigurable)]
    [hashtable[]] $Reasons
}

Aby zdefiniować właściwość Reasons jako właściwość złożoną, należy zdefiniować dla niej klasę, a następnie dodać ją do zasobu DSC:

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

    [DscProperty()]
    [string] $Phrase
}

class MyDscResource {
    [DscProperty(NotConfigurable)]
    [MyModuleReason[]] $Reasons
}

Uwaga

Klasa zdefiniowana dla właściwości Reasons nosi nazwę MyModuleReason zamiast Reason, używając nazwy modułu jako prefiksu. Chociaż można nadać klasie dowolną nazwę, jeśli co najmniej dwa moduły definiują klasę o tej samej nazwie i są używane w konfiguracji, program PowerShell zgłasza wyjątek.

Aby uniknąć wyjątków spowodowanych konfliktami nazw w konfiguracji DSC i maszyny, zawsze prefiks nazwy klasy zdefiniowanej dla właściwości Reasons .

Właściwości inne niż zasób

Podczas definiowania zasobu DSC opartego na klasie można dodać właściwości, które nie mają atrybutu DscProperty . Tych właściwości nie można używać bezpośrednio z konfiguracją Invoke-DscResource DSC lub w konfiguracji DSC. Mogą być używane wewnętrznie przez klasę lub bezpośrednio przez użytkownika tworzącego wystąpienie klasy.

Aby uzyskać więcej informacji na temat właściwości klasy, zobacz about_Classes.

Metody zasobów DSC oparte na klasach

Zasoby DSC oparte na klasach muszą implementować trzy metody:

  • Get() aby pobrać bieżący stan zasobu DSC
  • Test() aby sprawdzić, czy zasób DSC jest w żądanym stanie
  • Set() aby wymusić żądany stan zasobu DSC

Podpis metody jest definiowany przez oczekiwany typ danych wyjściowych i parametry. Klasa nie zostanie rozpoznana jako prawidłowy zasób DSC, jeśli nie zawiera prawidłowych podpisów dla tych metod.

Metody klas programu PowerShell różnią się od funkcji na kilka ważnych sposobów. Do celów pisania zasobu DSC opartego na klasie są następujące najważniejsze:

  • W metodach klas żadne obiekty nie są wysyłane do potoku, z wyjątkiem tych wymienionych w instrukcji return . Nie ma przypadkowych danych wyjściowych potoku z kodu. Jeśli metoda ma typ wyjściowy inny niż Void, należy określić instrukcję return , aby emitować obiekt tego typu.
  • Błędy niepowodujące zakończenia zapisane w strumieniu błędów z wewnątrz metody klasy nie są przekazywane. Należy użyć polecenia throw , aby wyświetlić błąd zakończenia.
  • Aby uzyskać dostęp do wartości właściwości wystąpienia klasy, użyj polecenia $this.<PropertyName>. Nie ustawiaj ani nie aktualizuj żadnych właściwości klasy, które mają atrybut DscProperty . Są one ustawiane, gdy użytkownik określa parametr Property z parametrem Invoke-DscResource lub podczas definiowania bloku zasobu DSC w konfiguracji DSC.

Aby uzyskać więcej informacji na temat metod klas, zobacz about_Classes.

Metody mogą wywoływać polecenia cmdlet i polecenia natywne, w tym te zdefiniowane w tym samym module co zasób DSC oparty na klasie.

Get

Metoda Get() służy do pobierania bieżącego stanu zasobu DSC i zwracania go jako obiektu. Musi zdefiniować swoje dane wyjściowe jako samą klasę i nie przyjmować żadnych parametrów.

Na przykład zasób MyDscResource DSC oparty na klasie musi mieć ten podpis:

[MyDscResource] Get() {
    # Implementation here
}

Aby metoda Get() zwróciła prawidłowy obiekt, należy utworzyć wystąpienie klasy. Następnie możesz wypełnić właściwości tego wystąpienia bieżącymi wartościami z systemu. Na koniec użyj słowa kluczowego return , aby wyświetlić bieżący stan.

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

    if (Test-Path -Path $this.Path) {
        $CurrentState.Ensure = [Ensure]::Present
        $CurrentState.Path   = $this.Path
    } else {
        $CurrentState.Ensure = [Ensure]::Absent
    }

    return $CurrentState
}

W przykładowej implementacji Get() metoda inicjuje $CurrentState zmienną za pomocą konstruktora domyślnego MyDscResource klasy. Sprawdza, czy plik określony we właściwości Path istnieje. Jeśli tak, metoda ustawia właściwości Upewnij się i Ścieżka na i $CurrentStatePresent odpowiednią ścieżkę. Jeśli tak nie jest, metoda ustawia wartość Upewnij się , że Absentwartość . Na koniec metoda używa return instrukcji do wysyłania bieżącego stanu jako danych wyjściowych.

Testowanie

Metoda Test() służy do sprawdzania, czy zasób DSC jest w żądanym stanie i zwraca $true wartość , jeśli jest w żądanym stanie, czy $false też nie. Musi definiować dane wyjściowe logiczne i nie przyjmować żadnych parametrów.

Podpis Test() metody powinien być zawsze zgodny z następującymi elementami:

[bool] Test() {
    # Implementation here
}

Zamiast ponownie zaimplementować logikę z Get() metody, wywołaj Get() metodę i przypisz jej dane wyjściowe do zmiennej.

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

    $CurrentState = $this.Get()

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

    # Check remaining properties as needed.

    return $InDesiredState
}

W przykładowej implementacji Test() metoda inicjuje zmienną , $InDesiredStatetak jak $true przed ustawieniem $CurrentState wartości wyjściowej Get() metody dla zasobu DSC opartego na klasie.

Następnie sprawdza wartości właściwości określonych $CurrentState w wystąpieniu zasobu DSC, ustawiając wartość $InDesiredState , $false jeśli jakiekolwiek właściwości nie są w żądanym stanie.

Na koniec zwraca informację, czy wystąpienie zasobu DSC jest w żądanym stanie z instrukcją return .

Set

Metoda Set() służy do wymuszania żądanego stanu zasobu DSC. Nie ma żadnych danych wyjściowych i nie przyjmuje żadnych parametrów.

Podpis Set() metody powinien być zawsze zgodny z następującymi elementami:

[void] Set() {
    # Implementation here
}

Set() Implementacja metody nie może używać żadnych return instrukcji. Należy go zapisać, aby idempotentnie wymusić żądany stan.

Uwaga

Może być konieczne pobranie bieżącego stanu za Get() pomocą metody, jeśli musisz wymusić żądany stan w zależności od bieżącego stanu systemu.

Na przykład możesz mieć logikę tworzenia usługi, gdy nie istnieje, zamiast poprawiać nieprawidłową wartość właściwości.

Dlatego ważne jest również użycie metody Invoke-DscResource w celu wywołania Test() metody i wywołanie Set() metody tylko wtedy, gdy Test() zwraca $falsewartość . Mimo że wszystkie zasoby DSC powinny być idempotentne, nie masz gwarancji, że każdy zasób DSC jest naprawdę idempotentny bez przeglądania jego implementacji.

Metody opcjonalne

Poza wymaganymi Get()metodami , Test()i Set() zasób DSC oparty na klasie może zdefiniować dowolną liczbę dodatkowych metod. Jednym z przypadków użycia jest zdefiniowanie metod pomocnika, takich jak kod używany w więcej niż jednej z wymaganych metod.

Jest to również przydatne podczas definiowania klasy reprezentującej składnik oprogramowania w celu uzyskania więcej niż tylko konfiguracji. Na przykład można zdefiniować klasę, która jest zarówno zasobem DSC, który umożliwia idempotentną konfigurację aplikacji, jak i wywołanie samej aplikacji do wykonywania zadań. Umożliwiłoby to zdefiniowanie klasy raz i użycie jej zarówno w przypadku rozszerzenia DSC, jak i funkcji wyeksportowanych z modułu na potrzeby korzystania z aplikacji.

Konstruktory

Konstruktor to metoda, która tworzy nowe wystąpienie klasy. Nazwa metody jest zawsze taka sama jak nazwa klasy i nie definiuje typu danych wyjściowych.

Nie jest obowiązkowe zdefiniowanie żadnych konstruktorów dla zasobu DSC opartego na klasie. Jeśli nie zdefiniujesz konstruktora, zostanie użyty domyślny konstruktor bez parametrów. Ten konstruktor inicjuje wszystkie elementy członkowskie do ich wartości domyślnych. Typy obiektów i ciągi mają wartości null.

Podczas definiowania konstruktora nie jest tworzony domyślny konstruktor bez parametrów. Zasób DSC oparty na klasie musi mieć konstruktor bez parametrów, więc jeśli zdefiniujesz dowolne konstruktory niestandardowe, co najmniej jeden z nich musi być zdefiniowany bez żadnych parametrów.

Gdy używasz Invoke-DscResource lub kompilujesz konfigurację DSC, zasób DSC jest tworzony za pomocą konstruktora bez parametrów, a następnie każda określona właściwość jest ustawiana na wystąpieniu.

Uwaga

Podczas definiowania konstruktora należy zgłosić wyjątek tylko wtedy, gdy zasób DSC nie jest prawidłowy w systemie z jakiegoś powodu. Na przykład zasób DSC oparty na klasie, który działa tylko w systemie Windows, może zgłosić wyjątek, jeśli został utworzony w systemie spoza systemu Windows.

Aby uzyskać więcej informacji na temat konstruktorów, zobacz about_Classes

Definiowanie konstruktora domyślnego

Zasoby DSC oparte na klasach wymagają, aby klasa implementuje nie konstruktorów lub jeden z tym podpisem:

<DscResourceClassName>() {
    # Implementation here
}

Jeśli nie ma wymaganej logiki do wykonania, na przykład ustawiania wartości domyślnych na podstawie systemu operacyjnego, nie musisz pisać żadnego kodu w konstruktorze. W poniższym przykładzie przedstawiono minimalną definicję konstruktora domyślnego:

MyDscResource() {}

Możesz dodać kod do konstruktora, aby ustawić wartości domyślne właściwości klasy. Na przykład możesz ustawić wartość na podstawie docelowego systemu operacyjnego:

MyDscResource() {
    if ($IsWindows) {
        $this.Format = 'JSON'
    } else {
        $this.Format = 'YAML'
    }
}

Uwaga

Pamiętaj, że walidacja właściwości w usłudze DSC odbywa się po użyciu konstruktora, a nie podczas. Nie próbuj weryfikować żadnych właściwości w konstruktorze.

Definiowanie konstruktora niestandardowego

Rozszerzenie DSC wywołuje tylko konstruktor bez parametrów. Można jednak zdefiniować inne konstruktory z parametrami, jeśli klasa jest używana w innych okolicznościach, takich jak funkcje w module.

Aby uzyskać więcej informacji na temat definiowania konstruktorów, zobacz about_Classes

Najlepsze rozwiązania

Jest to nie wyczerpująca lista najlepszych rozwiązań dotyczących tworzenia wysokiej jakości zasobów DSC opartych na klasie, które są idempotentne, bezpieczne i konserwowalne. Uzupełnia on listę kontrolną tworzenia zasobów DSC, która definiuje bardziej ogólne wskazówki dotyczące tworzenia zasobów DSC. Praktyki w tej sekcji są specyficzne dla zasobów DSC opartych na klasach.

Używanie atrybutów weryfikacji

Jeśli możesz zweryfikować właściwość z co najmniej jednym atrybutem weryfikacji, zrób to. Ta walidacja jest sprawdzana przed wywołaniem dowolnej metody za pomocą Invoke-DscResource polecenia i podczas kompilowania konfiguracji DSC. Podniesienie błędu wcześniej zmniejsza prawdopodobieństwo, że zasób DSC zakończy się niepowodzeniem w nieprzewidywalny sposób podczas wymuszania stanu.

Błędy zgłaszane przez wbudowane atrybuty weryfikacji są również jasne, która właściwość ma nieprawidłową wartość i jak wartość była nieprawidłowa.

Uwaga

Użyj tylko atrybutów weryfikacji, aby upewnić się, że dane wejściowe użytkownika dla właściwości są prawidłowe, a nie sprawdzić, czy właściwość jest w prawidłowym stanie. To jest Test() metoda dla.

Na przykład nie należy weryfikować, czy wartość ścieżka istnieje już, chyba że jest wymagana do działania pozostałej części logiki zasobu DSC. Jeśli zasób DSC tworzy plik w tej lokalizacji, nie weryfikuj jego istnienia w deklaracji właściwości.

Jeśli używasz żadnych złożonych właściwości, pamiętaj o zastosowaniu atrybutów weryfikacji do tych podwłaściwości. Te podwłaściwości są weryfikowane w tym samym czasie co ich właściwość nadrzędna.

Użyj wyliczenia zamiast funkcji ValidateSet

Jeśli właściwość zasobu DSC klasy ma listę prawidłowych wartości, które akceptuje, zdefiniuj ją jako właściwość wyliczenia zamiast użyć atrybutu ValidateSet .

Zapewnia to użytkownikom lepszy komunikat o błędzie i ułatwia konserwację, jeśli używasz tych wartości w dowolnym miejscu w module. Zamiast aktualizować każde polecenie cmdlet lub sprawdzać dla tej właściwości, możesz zaktualizować definicję wyliczenia.

Pamiętaj, że wyliczenia są właściwościami typu wartości. Domyślnie są one tworzone 0 po utworzeniu wystąpienia zasobu DSC opartego na klasie. Jeśli ustawisz jawną wartość domyślną dla właściwości wyliczenia, to wyliczenie nie może być niezarządzane. Jeśli użytkownik nie określi właściwości, zasób DSC zachowuje się tak samo, jakby użytkownik jawnie określił wartość domyślną.

Aby obsługiwać niezarządzane właściwości wyliczenia, pamiętaj, aby nie definiować etykiety dla 0 wartości. Domyślnie, jeśli nie określisz wartości całkowitej dla żadnych etykiet podczas korzystania z enum instrukcji, pierwsza zadeklarowana etykieta ma wartość 0. Zamiast tego zdefiniuj pierwszą etykietę z wartością 1 (lub dowolną wyższą wartością).

Na przykład:

enum OptionalSetting {
    FirstOption = 1
    SecondOption
    ThirdOption
}

Następnie w metodach Test() i Set() można zignorować właściwość wyliczenia, jeśli wartość to 0. Jeśli Test()właściwość wyliczenia to 0, zignoruj bieżący stan zasobu DSC w systemie. Nie zgłaszaj zasobu DSC jako żądanego stanu, jeśli bieżący stan jest prawidłową wartością. W Set()systemie upewnij się, że logika modyfikowania stanu systemu ignoruje właściwość wyliczenia, jeśli jest 0to .

Uwaga

Ta metoda implementowania właściwości wyliczenia, które mogą być niezarządzane, działa tylko wtedy, gdy wartość bazowa etykiet wyliczenia nie ma znaczenia lub gdy 0 nie jest prawidłową wartością bazową.

Jawne definiowanie wartości domyślnych dla właściwości typu wartości

Podczas tworzenia zasobu DSC opartego na klasach upewnij się, że właściwości określają poprawne wartości domyślne dla każdej właściwości typu wartości. Należy upewnić się, że wartości domyślne pozostaną zsynchronizowane z wartościami składnika zarządzanymi przez zasób DSC.

Udokumentowanie zachowania tych właściwości dla użytkowników. Upewnij się, że w dokumentacji wyjaśniono, że te właściwości są ustawione na wartości domyślne, jeśli użytkownik nie określi ich podczas korzystania z zasobu DSC.

Upewnij się, że zasób DSC uwzględnia niezarządzane właściwości typu odwołania

Ponieważ właściwości typu odwołania inicjują właściwość typu , w przeciwieństwie do $nullwłaściwości typu wartości, zasób DSC może rozróżniać, czy właściwość typu odwołania została określona, czy nie. Upewnij się, że zasoby DSC ignorują niezarządzane właściwości typu odwołania w metodach Test() i Set() .

Jeśli Test()właściwość typu odwołania to $null, zignoruj bieżący stan zasobu DSC w systemie. Nie zgłaszaj zasobu DSC jako żądanego stanu, jeśli bieżący stan nie $nulljest .

W Set()systemie upewnij się, że logika modyfikowania stanu systemu ignoruje wszelkie właściwości typu odwołania, które są $null.

Używanie niestandardowego atrybutu weryfikacji zamiast ValidateScript

W przypadku właściwości wymagających bardziej złożonej weryfikacji należy rozważyć zdefiniowanie własnego atrybutu dziedziczonego z klasy ValidateArgumentsAttribute lub jednego z jej pochodnych.

Zapewnia to znacznie większą kontrolę nad weryfikacją właściwości i komunikatami w przypadku niepowodzenia walidacji określonej wartości.

Na przykład ta definicja atrybutu ValidateHttpsUrl gwarantuje, że określona wartość jest prawidłowym adresem URL HTTPS.

using namespace System.Management.Automation

class ValidateHttps : ValidateArgumentsAttribute {
    [void]  Validate([object]$Url, [EngineIntrinsics]$engineIntrinsics) {
        [uri]$Uri = $Url

        if($Uri.Scheme -ne 'https') {
            $Message = @(
                "Specified value '$Url' is not a valid HTTPS URL."
                "Specify an absolute URL that begins with 'https://'."
            ) -join ' '

            throw [System.ArgumentException]::new($Message)
        }
    }
}

Po zastosowaniu do właściwości zasób DSC zgłasza przydatny komunikat o błędzie:

$Parameters = @{
    Name       = 'MyDscResource'
    ModuleName = 'MyDscResources'
    Method     = 'Get'
    Property   = @{
      Url = 'http://contoso.com/updater'
    }
}

Invoke-DscResource @Parameters -ErrorAction Stop
Invoke-DscClassBasedResource: Exception setting "Url": "Specified value
'http://contoso.com/updater'  is not a valid HTTPS URL. Specify an absolute
URL that begins with 'https://'."

Uwaga

Ze względu na ograniczenia w rozszerzeniu DSC nie można zdefiniować i użyć niestandardowego atrybutu weryfikacji w tym samym module co zasób DSC oparty na klasie. Zamiast tego należy zdefiniować niestandardowy atrybut weryfikacji w osobnym .psm1 pliku, dodać go do manifestu modułu głównego w ustawieniu NestedModules i określić instrukcję using w pliku, w którym zdefiniowany jest zasób DSC klasy.

Jeśli na przykład zdefiniowano atrybut ValidateHttps w Validators.psm1pliku , musisz mieć go w manifeście modułu:

{
    NestedModules = @(
        'Validators.psm1'
    )
}

W górnej części pliku modułu zdefiniujesz zasób DSC oparty na klasie:

using module ./Validators.psm1

W tym przykładzie Validators.psm1 znajduje się w tym samym folderze co moduł, w którym zdefiniowano zasób DSC oparty na klasie. Jeśli pliki znajdują się w różnych folderach, należy określić ścieżkę względną do modułu, który definiuje atrybut weryfikacji.

Używanie złożonych właściwości zamiast tabel skrótów

Jeśli zasób DSC ma właściwość ze znanymi podwłaściwościami, utwórz dla niej klasę i zdefiniuj te podwłaściwości w tej klasie. Zapewnia to bardziej wykrywalną powierzchnię ustawień i umożliwia zastosowanie walidacji w podwłaściwościach. Aby uzyskać więcej informacji, zobacz złożone właściwości.

Dodawanie metody walidacji, jeśli właściwości są zależne od siebie

Być może masz zasób DSC, który ma właściwości, które muszą zostać połączone, aby można je było zweryfikować. Tych właściwości nie można zweryfikować za pomocą atrybutu weryfikacji. Dodaj metodę weryfikacji do zasobu DSC opartego na klasie i wywołaj ją na początku Get()metod , Test()i Set() .

Jeśli na przykład zasób DSC do zarządzania plikiem konfiguracji ma właściwości Ścieżka i Rozszerzenie , może być konieczne zweryfikowanie:

  • Czy rozszerzenie pliku określonego jako Ścieżka jest zgodne z wartością Extension lub Extension nie jest określone
  • To rozszerzenie jest określone, jeśli wartość Path jest folderem zamiast pliku

Metoda walidacji powinna mieć jednoznaczną nazwę, nie zwracać żadnych danych wyjściowych i zgłaszać, jeśli walidacja wystąpienia zakończy się niepowodzeniem.

[void] ValidatePath() {
    $ExtensionSpecified = ![string]::IsNullOrEmpty($this.Extension)
    $PathExtension = Split-Path -Path $this.Path -Extension

    if (
        $PathExtension -and
        $ExtensionSpecified -and
        ($PathExtension -ne $this.Extension)
    ) {
        $Message = @(
            "Specified Path '$($this.Path)' has an extension ('$PathExtension')"
            "which doesn't match the value of the Extension property"
            "'$($this.Extension)'. When specifying the Extension property with"
            "the Path property as a specific file, the extension of Path's"
            "value must be the same as the value of Extension or Extension must"
            "not be specified."
        ) -join ' '

        throw [System.ArgumentException]::new($Message)
    } elseif (!$ExtensionSpecified) {
        $Message = @(
            "Specified Path '$($this.Path)' has no extension and the Extension"
            "property wasn't specified. When the value of Path is a folder, the"
            "Extension property is mandatory. Specify a value for Extension."
        ) -join ' '

        throw [System.ArgumentException]::new($Message)
    }
}

Jeśli w ten sposób musisz zweryfikować kilka różnych parametrów lub grup parametrów, zdefiniuj ogólną metodę weryfikacji, która wywołuje inne. Użyj tej metody w Get()elementy , Test()i Set().

Wyodrębnianie udostępnionego kodu do metod lub funkcji

Jeśli metody są długie z złożoną logiką lub ponownie użyj tego samego kodu między nimi, utwórz metodę pomocnika lub funkcję i przenieś tam kod. Ułatwia to testowanie i konserwowanie zasobu DSC. Ułatwia to również odczytywanie i zrozumienie metod zasobu DSC.