| RFC-0242:設定功能 | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | 在元件架構中新增設定功能 |
| Gerrit 變更 | |
| 作者 | |
| 審查人員 | |
| 提交日期 (年-月-日) | 2024-02-05 |
| 審查日期 (年-月-日) | 2024-04-11 |
摘要
說明元件架構中的設定功能,以及將新增至 CML 檔案以支援這些功能的語法。
請注意,本文件會取代先前結構化設定 RFC 的部分內容,這些 RFC 已在先前技術一節中提及。
提振精神
Fuchsia 中的元件會使用結構化設定來取得設定值。目前,設定值大多是從元件的套件載入。父項元件可以在啟動動態元件時,強制設定設定值,但 Fuchsia 中的大多數元件都是靜態元件。
新增這項功能的原因有很多:
- 允許靜態父項設定子項設定。
- 將單一設定值傳送至多個元件。
- 從 CML 檔案提供設定值。
系統組裝是設定功能的第一個客戶,因為這項功能可移除技術債。由於目前無法為靜態元件提供設定,只能編輯該元件的套件,因此存在技術債。系統組件目前會開啟 Fuchsia 封裝,編輯其設定值檔案,然後重新封裝。這屬於技術債,因為它會變更套件的雜湊值,而設定值檔案在技術上是元件的「私有」API,不容易演進。
對於無法重建的樹狀結構外套件,設定功能可讓這些元件進行設定。目前無法在靜態拓撲中編輯這些元件的設定。
這項功能在日後許多設定用途中,可能都會相當實用。
利害關係人
協助人員:neelsa@google.com
審查者:
- 系統組裝:aaronwood@google.com
- 元件架構:geb@google.com
- 安全性:markdittmer@google.com
- 驅動程式架構:surajmalhotra@google.com
- 元件架構:wittrock@google.com
社交化:在撰寫 RFC 前,已與元件架構團隊討論過這個問題。
需求條件
CML 作者可透過「設定功能」設定靜態元件的設定值。這類值可透過拓撲進行設定值的路由,讓多個元件使用相同的值。透過拓撲傳送值可讓間接祖先指定值,而現有功能僅允許直接父項指定值。
如要與系統的其餘部分保持一致,設定功能應盡可能遵循現有的元件架構功能。
設計
設計的大部分內容是 CML 語法,用於宣告及轉送設定能力。設定能力在 CML 中定義了類型和值。設定能力會傳送至要使用該功能的元件。使用現有的結構化設定程式庫啟動元件時,使用設定能力的元件就能看到值。
以下是定義設定能力的範例:
// Configuration capabilities can be defined in any component.
// When a configuration capability is defined, a value must be set for it.
capabilities: [
{
// Define the name of the capability.
config: "fuchsia.netstack.UseNetstack3",
// Define the type of the configuration.
type: "bool",
// When defining a configuration capability, there *must* be a value.
// If the route for the configuration capability ends at this definition, the
// value of the capability will always be this value.
value: "true"
},
// The below shows a string config.
{
config: "fuchsia.config.MyString",
type: "string",
max_size: 100,
value: "test",
},
// The below shows a vector config.
{
config: "fuchsia.config.MyUint8Vector",
type: "vector",
element: { type: "uint8" },
max_count: 100,
value: [1, 2, 3 ],
},
]
config 能力 type、element、max_count、max_size 欄位與 config 節中的用法意義相同。config 節中支援的所有值,capabilities 區塊也支援。
type 欄位支援下列項目:
- bool
- uint8、uint16、uint32、uint64
- int8、int16、int32、int64
- string
- 向量
使用區塊支援與功能區塊相同的 type、element、max_count 和 max_size 欄位。
以下是使用設定能力的語法範例:
// Using a configuration capability means that this configuration will show
// up in the component's structured config at runtime with the specified `key`
// name.
// NOTE: Using a configuration capability will override the value in the Config
// Value File (CVF) and the value obtained from the "mutability" setting.
use: [
{
config: "fuchsia.netstack.LaunchProcess",
// This is the name that the component will see in its Structured Config
// struct. If the `use` is optional this must match a name in the "config"
// block of the component's manifest.
key: "can_launch_process",
// The using field needs the type information so that the component's
// Config Value File format can be created.
type: "bool",
// From is identical to other capabilities.
from: "parent",
},
// The below shows a vector config.
{
config: "fuchsia.netstack.MyUint8Vector",
key: "my_vector",
type: "vector",
element: { type: "uint8" },
max_count: 100,
from: "parent",
},
// The below shows a string config.
{
config: "fuchsia.netstack.MyString",
key: "my_string",
type: "string",
max_size: 256,
from: "parent",
},
]
以下是設定能力的路由語法範例:
// Expose and Offer behave the same as any other capability.
expose: [
{
config: "fuchsia.netstack.UseNetstack3",
as: "fuchsia.mycomponent.UseVersion3",
from: "self",
},
]
offer: [
{
config: "fuchsia.config.MyString",
as: "fuchsia.mycomponent.ProcessName",
from: "self",
to: "#mychild",
},
]
選用功能
如果元件使用的設定能力將可用性設為 optional,且該能力是從 void 路由傳送,則元件會收到設定值檔案 (CVF) 中的值。這項功能可支援軟遷移,以更新設定。
淘汰「config」區塊
在設定功能推出前,設定欄位是在 CML 的 config 節中宣告。這項資訊現在會由 use 節中的資訊取代。也就是說,為元件產生的結構化設定結構定義,會是 use 區塊和 config 節中的欄位宣告聯集。
所有結構化設定用戶端都遷移至設定功能後,系統就會移除 CML 中的設定區塊支援。
淘汰「mutability: parent」功能
在設定功能推出前,設定值可宣告為 mutability: parent,允許該元件的父項變更值。
這項功能的使用者會從上層移至 use 設定能力。所有使用者遷移完畢後,這項功能就會移除。
實作
這些 CML 功能的實作方式相對簡單,只要幾個 CL 即可在樹狀結構中完成。用戶隨時可以改用設定功能,因為這不會影響現有的結構化設定功能。
我們需要確保 Scrutiny 瞭解設定功能,並能驗證特定產品是否具有特定設定。
效能
由於元件架構需要對元件使用的設定功能執行路徑設定,因此啟動元件的速度可能會稍微變慢。如果功能來自未解析且需要下載的元件,這可能會造成重大影響。對於已解析的元件,這應該可以忽略不計。
人體工學
這項新 CML 能力的人體工學設計與現有功能相同。新增及路由設定能力時,可能需要較多的程式碼,但我們盡可能選擇與現有能力語法相符的語法。此外,我們也盡可能選擇與現有 config 區塊語法相符的語法。如果兩種語法發生衝突,系統會優先採用現有的能力語法。如果使用者熟悉元件架構,採用現有語法可減少認知負擔。
CF 團隊可能會決定保留 config 區塊,做為宣告設定能力的語法糖,或在需要更符合人體工學的設計時,新增其他語法糖。
回溯相容性
這項功能是新推出的。可回溯相容於現有的結構化設定功能。
請注意,將設定能力路徑傳送至元件時,一律會優先採用該路徑,而非 CVF 檔案中的值。如果元件有選用設定能力路徑,但該路徑不存在,系統就會使用 CVF 檔案中的值。
安全性考量
這項功能不會影響安全性。審查和其他調查 CML 的工具,都適用於這個新能力類型。
可以說,相較於在元件套件中編輯值的現有策略,以這種方式設定功能會更顯而易見。
如果元件使用必要設定能力,但系統未將設定功能路徑傳送至該元件,元件就無法啟動。這不應是安全性問題,因為元件的父項是受信任的,而且這些路徑可以靜態驗證是否正確。
隱私權注意事項
這項提案應不會影響隱私權。
測試
這項功能需要單元測試和整合測試。一般測試領域包括:
- 剖析新的 CML 語法。
- 透過拓撲路徑傳送新能力。
- 嘗試啟動缺少設定功能的元件。
- 嘗試啟動設定能力類型錯誤的元件。
- 使用設定能力啟動動態元件。
這項功能需要在 Scrutiny 中新增下列測試:
- 測試 Scrutiny 是否能解析設定功能的值。
- 測試不同設定值來源的優先順序/覆寫邏輯。
- 測試設定功能、設定區塊和可變性之間的互動。
這些測試都不需要新的測試基礎架構。
說明文件
Fuchsia.dev 必須更新,才能提供設定功能的說明文件。現有的能力文件將做為這份新文件的範本。
缺點、替代方案和未知事項
替代方案:實作設定覆寫服務
原始的結構化設定 RFC 建議直接從元件的套件取得結構化設定。RFC 特別指出,它不會嘗試處理「由其他元件 (父項元件和管理元件除外) 設定的設定資料」。替代方案是繼續不支援以能力為基礎的設定架構。
與覆寫服務相比,設定功能的一項缺點是較為冗長複雜。一開始,全域實作項目一律會比較簡單。不過,Fuchsia 發現從長遠來看,以能力為基礎的系統最終會更具可組合性,也更容易理解。如果能指出特定設定只會用於元件拓撲的子集,或在兩個不同元件中使用兩個不同的值,會非常有幫助。設定功能可讓您更輕鬆地表達這項功能,並體現 Fuchsia 其他地方使用的功能型系統。使用現有的 CML 語法進行設定,可讓 Fuchsia 開發人員更容易瞭解這項功能,並與元件架構的現有 工具妥善組合。
缺點:許多額外用途欄位
將型別資訊保留在 use 區塊中,會額外新增 6 個欄位,這些欄位僅適用於設定功能。
您可以將這 6 個欄位合併為一個欄位 (含子欄位),但新增欄位較為合適,因為這樣語法會與現有的 config 區塊語法相近。
缺點:混淆型別資訊和路由
將設定結構定義放在 use 宣告中,缺點是 use 區塊會定義型別資訊,也會定義路徑。部分元件可能想定義設定,但不指定路徑,然後在不同情境中以不同方式設定路徑。如果型別資訊位於 Use 區塊以外的位置,這項作業會比較簡單。
如要變更型別的定義方式,元件作者必須修改 use 區塊,而非只修改 config 區塊。
如果設定定義和路徑的組合持續為開發人員帶來困擾,元件架構團隊可能會重新審視這項決策。
替代做法:在 config 區塊中保留設定類型定義
另一種做法是在 use 宣告中不使用「type」欄位,而是依賴現有「config」區塊中的型別資訊。這就是本 RFC 舊版的狀況。這個替代方案可解決目前將型別資訊和路徑混淆的缺點。這項功能可讓用戶在一個位置定義設定,並在另一個位置 (可能包括不同的 CML 分片,根據不同設定以不同方式路由) 路由設定。
在目前以結構化設定為基礎的實作中,Component Manager 會在啟動元件時將設定「推送」至元件,因此 Component Manager 必須確保已路由能力類型與目標結構化設定欄位的類型相符。我們決定將型別資訊放在 use 宣告中,因為這與功能宣告是對稱的。Component Manager 執行路徑時,必須確保類型資訊一致,也就是說,邏輯上,資訊應包含在路徑的兩端 (功能和用途)。
在 use 宣告中保留型別資訊的另一個原因是,這樣一來,所有資訊都能保留在 use 宣告中,不需要相符的「config」區塊項目。這樣一來,CML 檔案中的資訊就會集中在單一位置,方便稽核。
替代做法:use 宣告中的 as 欄位
config 區塊中封裝的結構化設定欄位名稱和類型資訊,可用於指定提供能力的欄位。as這與 CML 中大多數非「重新命名」的 path 做法一致。
由於這個欄位的運作方式與其他 as 欄位不同,因此改用 key 一詞。as 通常為選填,但 key 為必填。如果能力為選用,key 也必須與 config 區塊中的現有鍵相符。
Unknown:平衡現有結構化設定與功能的不一致性
現有的結構化設定與其他功能運作方式不一致,原因如下:
其中一項不一致之處在於,程式會深度依附於元件資訊清單中定義的結構化設定格式。通常是資訊清單依附於程式,而結構化設定會使這種關係形成循環。這點可從結構化設定建構規則中看出,因為這些規則需要在元件、元件資訊清單和程式之間新增額外層級。這項循環不一致問題不會透過設定功能解決,但希望後續的 RFC 能解決這個問題。
另一個不一致之處是,結構化設定會在啟動時「推送」至元件,而其他功能則會在元件存取時「提取」。本 RFC 也未解決這項不一致的問題。這項 RFC 的目的是在元件資訊清單中新增路由和能力支援。本 RFC 不會變更程式與結構化設定之間的介面,因此需要遷移的次數有限。
實作設定功能並瞭解其用途後,Fuchsia 就能更妥善地解決這些不一致問題。更多客戶資料有助於我們解決痛點,並實施後續變更。
既有技術和參考資料
先前的結構化設定 RFC: