PowerShell sınıfları ile özel bir DSC kaynağı yazma
Şunun için geçerlidir: Windows PowerShell 5.0
Windows PowerShell 5.0'da PowerShell sınıflarının kullanıma sunulmasıyla, artık bir sınıf oluşturarak bir DSC kaynağı tanımlayabilirsiniz. sınıfı hem şemayı hem de kaynağın uygulamasını tanımlar, bu nedenle ayrı bir MOF dosyası oluşturmanıza gerek yoktur. DSCResources klasörü gerekli olmadığından, sınıf tabanlı bir kaynağın klasör yapısı da daha basittir.
Sınıf tabanlı bir DSC kaynağında şema, özellik türünü belirtmek için özniteliklerle değiştirilebilen sınıfın özellikleri olarak tanımlanır. Kaynak, Get()
, Set()
ve Test()
yöntemleri (betik kaynağındaki Get-TargetResource
, Set-TargetResource
ve Test-TargetResource
işlevlerine eşdeğerdir) tarafından uygulanır.
Bu makalede, belirtilen yolda bir dosyayı yöneten NewFile adlı basit bir kaynak oluşturacağız.
DSC kaynakları hakkında daha fazla bilgi için bkz. Özel Windows PowerShell İstenen Durum Yapılandırma Kaynakları oluşturma
Not
Genel koleksiyonlar sınıf tabanlı kaynaklarda desteklenmez.
Sınıf kaynağı için klasör yapısı
PowerShell sınıfına sahip bir DSC özel kaynağı uygulamak için aşağıdaki klasör yapısını oluşturun.
sınıfı MyDscResource.psm1
ve modül bildirimi MyDscResource.psd1
içinde tanımlanır.
$env:ProgramFiles\WindowsPowerShell\Modules (folder)
|- MyDscResource (folder)
MyDscResource.psm1
MyDscResource.psd1
Sınıfı oluşturma
Bir PowerShell sınıfı oluşturmak için class anahtar sözcüğünü kullanırsınız. Sınıfın bir DSC kaynağı olduğunu belirtmek için DscResource()
özniteliğini kullanın. sınıfının adı DSC kaynağının adıdır.
[DscResource()]
class NewFile {
}
Özellikleri bildirme
DSC kaynak şeması sınıfının özellikleri olarak tanımlanır. Üç özelliği aşağıdaki gibi bildiririz.
[DscProperty(Key)]
[string] $path
[DscProperty(Mandatory)]
[ensure] $ensure
[DscProperty()]
[string] $content
[DscProperty(NotConfigurable)]
[MyDscResourceReason[]] $Reasons
Özelliklerin öznitelikler tarafından değiştirildiğine dikkat edin. Özniteliklerin anlamı aşağıdaki gibidir:
- DscProperty(Anahtar): özelliği gereklidir. özelliği bir anahtardır. Anahtar olarak işaretlenmiş tüm özelliklerin değerleri, yapılandırma içindeki bir kaynak örneğini benzersiz olarak tanımlamak için birleştirilmelidir.
- DscProperty(Zorunlu): Özelliği gereklidir.
-
DscProperty(NotConfigurable): Özelliği salt okunurdur. Bu öznitelikle işaretlenmiş özellikler bir yapılandırma tarafından ayarlanamaz, ancak mevcut olduğunda
Get()
yöntemiyle doldurulur. - DscProperty(): Özelliği yapılandırılabilir, ancak gerekli değildir.
$Path
ve $SourcePath
özellikleri her iki dizedir.
$CreationTime
bir DateTime özelliğidir.
$Ensure
özelliği, aşağıdaki gibi tanımlanan bir numaralandırma türüdür.
enum Ensure
{
Absent
Present
}
Sınıfları ekleme
Kaynağınızda kullanabileceğiniz tanımlı özelliklere sahip yeni bir tür eklemek isterseniz, yukarıda açıklandığı gibi özellik türlerine sahip bir sınıf oluşturmanız yeter.
class MyDscResourceReason {
[DscProperty()]
[string] $Code
[DscProperty()]
[string] $Phrase
}
Not
MyDscResourceReason
sınıfı burada modülün adı ön ek olarak bildirilir. Katıştırılmış sınıflara herhangi bir ad verebilirsiniz, ancak iki veya daha fazla modül aynı ada sahip bir sınıf tanımlarsa ve her ikisi de bir yapılandırmada kullanılırsa PowerShell bir özel durum oluşturur.
DSC'de ad çakışmalarından kaynaklanan özel durumları önlemek için, katıştırılmış sınıflarınızın adlarını modül adıyla ön ekleyin. Katıştırılmış sınıfınızın adı zaten çakışma olasılığı düşükse, bunu ön ek olmadan kullanabilirsiniz.
DSC Kaynağınız Azure Automanage'ın makine yapılandırma özelliğiyle kullanılmak üzere tasarlanmışsa, Nedenler özelliği için her zaman oluşturduğunuz eklenmiş sınıfın adını önekleyin.
Genel ve Özel işlevler
Aynı modül dosyasında PowerShell işlevleri oluşturabilir ve bunları DSC sınıf kaynağınızın yöntemleri içinde kullanabilirsiniz. İşlevlerin genel olarak bildirilmesi gerekir, ancak bu ortak işlevlerin içindeki betik blokları özel işlevleri çağırabilir. Tek fark, bunların modül bildiriminin FunctionsToExport
özelliğinde listelenip listelenmedikleridir.
<#
Public Functions
#>
function Get-File {
param(
[ensure]$ensure,
[parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]$path,
[String]$content
)
$fileContent = [MyDscResourceReason]::new()
$fileContent.code = 'file:file:content'
$filePresent = [MyDscResourceReason]::new()
$filePresent.code = 'file:file:path'
$ensureReturn = 'Absent'
$fileExists = Test-path $path -ErrorAction SilentlyContinue
if ($true -eq $fileExists) {
$filePresent.phrase = "The file was expected to be: $ensure`nThe file exists at path: $path"
$existingFileContent = Get-Content $path -Raw
if ([string]::IsNullOrEmpty($existingFileContent)) {
$existingFileContent = ''
}
if ($false -eq ([string]::IsNullOrEmpty($content))) {
$content = $content | ConvertTo-SpecialChars
}
$fileContent.phrase = "The file was expected to contain: $content`nThe file contained: $existingFileContent"
if ($content -eq $existingFileContent) {
$ensureReturn = 'Present'
}
}
else {
$filePresent.phrase = "The file was expected to be: $ensure`nThe file does not exist at path: $path"
$path = 'file not found'
}
return @{
ensure = $ensureReturn
path = $path
content = $existingFileContent
Reasons = @($filePresent,$fileContent)
}
}
function Set-File {
param(
[ensure]$ensure = "Present",
[parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]$path,
[String]$content
)
Remove-Item $path -Force -ErrorAction SilentlyContinue
if ($ensure -eq "Present") {
New-Item $path -ItemType File -Force
if ([ValidateNotNullOrEmpty()]$content) {
$content | ConvertTo-SpecialChars | Set-Content $path -NoNewline -Force
}
}
}
function Test-File {
param(
[ensure]$ensure = "Present",
[parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]$path,
[String]$content
)
$test = $false
$get = Get-File @PSBoundParameters
if ($get.ensure -eq $ensure) {
$test = $true
}
return $test
}
<#
Private Functions
#>
function ConvertTo-SpecialChars {
param(
[parameter(Mandatory = $true,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string]$string
)
$specialChars = @{
'`n' = "`n"
'\\n' = "`n"
'`r' = "`r"
'\\r' = "`r"
'`t' = "`t"
'\\t' = "`t"
}
foreach ($char in $specialChars.Keys) {
$string = $string -replace ($char,$specialChars[$char])
}
return $string
}
Yöntemleri uygulama
Get()
, Set()
ve Test()
yöntemleri, betik kaynağındaki Get-TargetResource
, Set-TargetResource
ve Test-TargetResource
işlevlerine benzer.
En iyi yöntem olarak, sınıf uygulaması içindeki kod miktarını en aza indirin. Bunun yerine kodunuzun büyük bölümünü modüldeki genel işlevlere taşıyın. Bu işlev bağımsız olarak test edilebilir.
<#
This method is equivalent of the Get-TargetResource script function.
The implementation should use the keys to find appropriate
resources. This method returns an instance of this class with the
updated key properties.
#>
[NewFile] Get() {
$get = Get-File -ensure $this.ensure -path $this.path -content $this.content
return $get
}
<#
This method is equivalent of the Set-TargetResource script function.
It sets the resource to the desired state.
#>
[void] Set() {
$set = Set-File -ensure $this.ensure -path $this.path -content $this.content
}
<#
This method is equivalent of the Test-TargetResource script
function. It should return True or False, showing whether the
resource is in a desired state.
#>
[bool] Test() {
$test = Test-File -ensure $this.ensure -path $this.path -content $this.content
return $test
}
Dosyanın tamamı
Tam sınıf dosyası aşağıdaki gibidir.
enum ensure {
Absent
Present
}
<#
This class is used within the DSC Resource to standardize how data
is returned about the compliance details of the machine. Note that
the class name is prefixed with the module name - this helps prevent
errors raised when multiple modules with DSC Resources define the
Reasons property for reporting when they're out-of-state.
#>
class MyDscResourceReason {
[DscProperty()]
[string] $Code
[DscProperty()]
[string] $Phrase
}
<#
Public Functions
#>
function Get-File {
param(
[ensure]$ensure,
[parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]$path,
[String]$content
)
$fileContent = [MyDscResourceReason]::new()
$fileContent.code = 'file:file:content'
$filePresent = [MyDscResourceReason]::new()
$filePresent.code = 'file:file:path'
$ensureReturn = 'Absent'
$fileExists = Test-path $path -ErrorAction SilentlyContinue
if ($true -eq $fileExists) {
$filePresent.phrase = "The file was expected to be: $ensure`nThe file exists at path: $path"
$existingFileContent = Get-Content $path -Raw
if ([string]::IsNullOrEmpty($existingFileContent)) {
$existingFileContent = ''
}
if ($false -eq ([string]::IsNullOrEmpty($content))) {
$content = $content | ConvertTo-SpecialChars
}
$fileContent.phrase = "The file was expected to contain: $content`nThe file contained: $existingFileContent"
if ($content -eq $existingFileContent) {
$ensureReturn = 'Present'
}
}
else {
$filePresent.phrase = "The file was expected to be: $ensure`nThe file does not exist at path: $path"
$path = 'file not found'
}
return @{
ensure = $ensureReturn
path = $path
content = $existingFileContent
Reasons = @($filePresent,$fileContent)
}
}
function Set-File {
param(
[ensure]$ensure = "Present",
[parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]$path,
[String]$content
)
Remove-Item $path -Force -ErrorAction SilentlyContinue
if ($ensure -eq "Present") {
New-Item $path -ItemType File -Force
if ([ValidateNotNullOrEmpty()]$content) {
$content | ConvertTo-SpecialChars | Set-Content $path -NoNewline -Force
}
}
}
function Test-File {
param(
[ensure]$ensure = "Present",
[parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]$path,
[String]$content
)
$test = $false
$get = Get-File @PSBoundParameters
if ($get.ensure -eq $ensure) {
$test = $true
}
return $test
}
<#
Private Functions
#>
function ConvertTo-SpecialChars {
param(
[parameter(Mandatory = $true,ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[string]$string
)
$specialChars = @{
'`n' = "`n"
'\\n' = "`n"
'`r' = "`r"
'\\r' = "`r"
'`t' = "`t"
'\\t' = "`t"
}
foreach ($char in $specialChars.Keys) {
$string = $string -replace ($char,$specialChars[$char])
}
return $string
}
<#
This resource manages the file in a specific path.
[DscResource()] indicates the class is a DSC resource
#>
[DscResource()]
class NewFile {
<#
This property is the fully qualified path to the file that is
expected to be present or absent.
The [DscProperty(Key)] attribute indicates the property is a
key and its value uniquely identifies a resource instance.
Defining this attribute also means the property is required
and DSC will ensure a value is set before calling the resource.
A DSC resource must define at least one key property.
#>
[DscProperty(Key)]
[string] $path
<#
This property indicates if the settings should be present or absent
on the system. For present, the resource ensures the file pointed
to by $Path exists. For absent, it ensures the file point to by
$Path does not exist.
The [DscProperty(Mandatory)] attribute indicates the property is
required and DSC will guarantee it is set.
If Mandatory is not specified or if it is defined as
Mandatory=$false, the value is not guaranteed to be set when DSC
calls the resource. This is appropriate for optional properties.
#>
[DscProperty(Mandatory)]
[ensure] $ensure
<#
This property is optional. When provided, the content of the file
will be overwridden by this value.
#>
[DscProperty()]
[string] $content
<#
This property reports the reasons the machine is or is not compliant.
[DscProperty(NotConfigurable)] attribute indicates the property is
not configurable in DSC configuration. Properties marked this way
are populated by the Get() method to report additional details
about the resource when it is present.
#>
[DscProperty(NotConfigurable)]
[MyDscResourceReason[]] $Reasons
<#
This method is equivalent of the Get-TargetResource script function.
The implementation should use the keys to find appropriate
resources. This method returns an instance of this class with the
updated key properties.
#>
[NewFile] Get() {
$get = Get-File -ensure $this.ensure -path $this.path -content $this.content
return $get
}
<#
This method is equivalent of the Set-TargetResource script function.
It sets the resource to the desired state.
#>
[void] Set() {
$set = Set-File -ensure $this.ensure -path $this.path -content $this.content
}
<#
This method is equivalent of the Test-TargetResource script
function. It should return True or False, showing whether the
resource is in a desired state.
#>
[bool] Test() {
$test = Test-File -ensure $this.ensure -path $this.path -content $this.content
return $test
}
}
Bildirim oluşturma
Sınıf tabanlı bir kaynağı DSC altyapısının kullanımına açmak için bildirim dosyasına modülün kaynağı dışarı aktarmasını belirten bir DscResourcesToExport
deyimi eklemeniz gerekir. Bildirimimiz şu şekilde görünür:
@{
# Script module or binary module file associated with this manifest.
RootModule = 'NewFile.psm1'
# Version number of this module.
ModuleVersion = '1.0.0'
# ID used to uniquely identify this module
GUID = 'fad0d04e-65d9-4e87-aa17-39de1d008ee4'
# Author of this module
Author = 'Microsoft Corporation'
# Company or vendor of this module
CompanyName = 'Microsoft Corporation'
# Copyright statement for this module
Copyright = ''
# Description of the functionality provided by this module
Description = 'Create and set content of a file'
# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '5.0'
# Functions to export from this module
FunctionsToExport = @('Get-File','Set-File','Test-File')
# DSC resources to export from this module
DscResourcesToExport = @('NewFile')
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
# Tags = @(Power Plan, Energy, Battery)
# A URL to the license for this module.
# LicenseUri = ''
# A URL to the main website for this project.
# ProjectUri = ''
# A URL to an icon representing this module.
# IconUri = ''
# ReleaseNotes of this module
# ReleaseNotes = ''
} # End of PSData hashtable
}
}
Kaynağı test edin
Sınıf ve bildirim dosyalarını daha önce açıklandığı gibi klasör yapısına kaydettikten sonra, yeni kaynağı kullanan bir yapılandırma oluşturabilirsiniz. DSC yapılandırması çalıştırma hakkında bilgi için bkz.yapılandırmaları /tmp/test.txt
dosyasının var olup olmadığını ve içeriğin 'Content' özelliği tarafından sağlanan dizeyle eşleşip eşleşmediğini denetler. Aksi takdirde, dosyanın tamamı yazılır.
Configuration MyConfig
{
Import-DSCResource -ModuleName NewFile
NewFile testFile
{
Path = "/tmp/test.txt"
Content = "DSC Rocks!"
Ensure = "Present"
}
}
MyConfig
PsDscRunAsCredential'ı destekleme
[Not] PsDscRunAsCredential PowerShell 5.0 ve sonraki sürümlerde desteklenir.
PsDscRunAsCredential özelliği, kaynağın belirtilen kimlik bilgileri kümesi altında çalıştırılması gerektiğini belirtmek için DSC yapılandırmalarında kaynak bloğunda kullanılabilir. Daha fazla bilgi için bkz.kullanıcı kimlik bilgileriyle DSC çalıştırma
Kaynağınız için PsDscRunAsCredential gerektirme veya izin verme
-
Optional
PsDscRunAsCredential bu kaynağı çağıran yapılandırmalar için isteğe bağlıdır. Bu varsayılan değerdir. -
Mandatory
PsDscRunAsCredential bu kaynağı çağıran tüm yapılandırmalar için kullanılmalıdır. - bu kaynağı çağıran
NotSupported
Yapılandırmaları PsDscRunAsCredentialkullanamaz. -
Default
Optional
ile aynıdır.
Örneğin, özel kaynağınızın PsDscRunAsCredentialkullanılmasını desteklemediğini belirtmek için aşağıdaki özniteliği kullanın:
[DscResource(RunAsCredential=NotSupported)]
class NewFile {
}
Modülde birden çok sınıf kaynağı bildirme
Modül, birden çok sınıf tabanlı DSC kaynağı tanımlayabilir. Yalnızca aynı .psm1
dosyasındaki tüm sınıfları bildirmeniz ve her adı .psd1
bildirimine eklemeniz gerekir.
$env:ProgramFiles\WindowsPowerShell\Modules (folder)
|- MyDscResource (folder)
|- MyDscResource.psm1
MyDscResource.psd1
Kullanıcı bağlamını erişme
Özel bir kaynağın içinden kullanıcı bağlamlarına erişmek için $global:PsDscContext
otomatik değişkenini kullanabilirsiniz.
Örneğin aşağıdaki kod, kaynağın çalıştığı kullanıcı bağlamını ayrıntılı çıkış akışına yazar:
if (PsDscContext.RunAsUser) {
Write-Verbose "User: $global:PsDscContext.RunAsUser";
}
Ayrıca Bkz.
Özel Windows PowerShell İstenen Durum Yapılandırma Kaynakları oluşturma