構建DSC 資源的”另類寫法”



構建DSC 資源的"另類寫法"


今天我們要說的另類寫法並不是什麼新鮮東西

而且 這篇博客也遲到了一年甚至更多,

雖然我個人採用這個寫法的資源很早之前就在 Gallery發佈,並且持續更新,

(有關我個人發佈資源 請在 Gallery 搜索 strike 有任何好的建議或者資源bug或者其他問題也請直接聯繫我)

卻總沒想起認真的總結這個寫法


這個寫法並不是我在2014年發佈的那個寫法 當然新的PS V5 5.1依然支持那個寫法

但是更多的資源 都採用這個新的寫法,由於我個人並沒有找到這個寫法的官方的確切的說明 我姑且稱之爲 "嵌套類",事實上 就是嵌套 一個CIM類的實例中的屬性是另外一個類的實例

說着彆扭 但是很好理解

首先我們看看以前的MOF中的定義

下圖是以前的類的定義 ,

如果你需要多個屬性的話你還可以繼續添加  當然 你可以硬編碼這些 ,

你也可以用工具完成 這裏不在多說



廢話不多說

下面來看這個 另類的寫法

這是MOF 中對資源的定義 看起來就是多了一個類而已

當我們用 (Get-DscResource t_Demo).Properties 查看這資源時候你會發現其中的一個屬性不在是你熟悉的那些基本的屬性 如下所示


我們發現Child 屬性是一個叫 t_Demo_Child 的屬性

這個就是我們說的 CIM類的實例的屬性是其他cim類的實例

這時候你可以看見 Child 屬性只接受一個值  如果我要多個值呢

那麼我們去更改mof中的

[Write,EmbeddedInstance("t_Demo_Child")] String Child[這部分爲


[Write,EmbeddedInstance("t_Demo_Child")] String Child[];

就是在Child 之後加上 [] 來標記這個屬性有多個值

那麼問題來了 這個t_Demo_Child類定義和以前一樣麼 答案是完全一樣 以前怎麼定義還怎麼定義 Key 該要還是得要不得省略


好了 我們說完架構的問題 然後我們要來說說怎麼在資源裏處理這個屬性

我們首先用Test-TargetResource 的PS版本命令做演示

第一 我們要添加這個屬性對應的參數 如下所示

請一定記住 處理這類屬性 一定是 ciminstance

首先我們要找出這個實例中  包含用戶修改的屬性 因爲demo中沒有定義可選

的屬性 所以本例中可以不進行判斷 但是實際中可能出現用戶未定義的屬性這時候就需要判斷下了

判斷下是否經過用戶修改

當然這個辦法稍顯複雜

我們還是繼續說這個判斷過後的做法 稍後會有一個更簡單的辦法來解決他

$haschange.where({$_.Name -eq 'Child_Ensure'}).value 這樣我們就獲取了Child_Ensure 的值

你還可以如法炮製獲取其他的值


下圖給出類 $haschange 的 屬性結構

其實你完全可以把他當成哈希表來理解

好了 關於篩選取值的笨方法我們說過了

我們來說說簡單的辦法


$Child.'Child_Ensur' 我們完全可以用這個方法快速獲取你要的屬性值

好了 test 和set 部分如法炮製 千萬記得  如果不是必須屬性 在使用前記得判斷是否爲空 否則拋出異常就不好玩了

代碼的強壯型不單靠錯誤處理 邏輯的嚴謹性也很重要

現在  我們來說說 get

在這種寫法下 我們依然可以採用老套路 get 部分返回一個哈希表

這是一個經典的寫法 依然十分有效

但是我想介紹另外一種寫法

首先 我們依然還是要返回一個哈希表 用於最外層

也就是返回 t_Demo 這個類的屬性 除了嵌套的類的屬性 本例中就是除了Child這個屬性 當然 Ensure可以不返回 因爲沒有意義如下所示

此後我們先運行配置 然後get一下 如下所示


然後我們依然 可以新建哈希表用戶Child 屬性 並且把這個哈希表作爲$re的一個屬性一起返回

然後我們get  但是結果不盡人意 如下所示 當我們查看Child 時候發現完全不是我們要的結果


所以  第二種方案  採用New-CimInstance 如下圖

道理十分簡單 由於我們的MOF中定義了child 屬性是多個值 那麼 我們理應返回一個數組

這就是$re_child 要提前聲明數組的原因

(New-CimInstance -Namespace "root/Microsoft/Windows/DesiredStateConfiguration" `

-ClassName t_Demo_Child -Property @{Child_Name = "T_name"} -ClientOnly)


至於這段代碼 則是new 一個新的實例 由於我們經過 test set 傳入的是 CimInstance 那麼我們一樣返回 一個CimInstance  而-Property @{Child_Name = "T_name"} 這部分則是 該類中定義的key 作爲初始化該CimInstance必須的屬性 所以我們必須寫Child_Name

由於本例中並沒有定義任何 dsc資源屬性爲Required 否則 標記爲 Required 的屬性一樣需要返回,

此後我們再次get 效果如下

至此 這個另類的寫法我們已經完成

下面附上 配置

Configuration T
{
Import-DscResource -ModuleName t_demo
Node localhost
{
t_Demo d
{
Ensure = 'Present'
Name = "T_name"
Child =  t_Demo_Child
{
Child_Name = "Child"
Child_Ensure = 'Present'
}
}
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章