RFC-0242:設定功能

RFC-0242:設定功能
狀態已接受
區域
  • 元件架構
說明

為元件架構新增設定功能

Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2024-02-05
審查日期 (年-月-日)2024-04-11

摘要

概述元件架構中設定capabilities的用法,以及將加入 CML 檔案的語法以支援這些功能。

請注意,本文件取代先前結構化設定 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 能力上的 typeelementmax_countmax_size 欄位與 config 段落中的用法相同。config 節內支援的所有值,也都支援在 capabilities 區塊中使用。

type 欄位支援下列功能:

  • 布林值
  • uint8、uint16、uint32、uint64
  • int8、int16、int32、int64
  • string
  • 向量

using 區塊支援與功能區塊相同的 typeelementmax_countmax_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 檔案中的值。

安全性考量

這項功能不應影響安全性。Scrutiny 和其他 CML 檢查工具可用於這類新能力。

可以說,以這種方式設定功能比在元件套件中編輯值的現有策略更容易讓人察覺。

如果元件使用必要的設定能力,但沒有任何功能會路由至該元件,則元件將無法啟動。由於元件的父項是可信任的,且這些路徑可經過靜態驗證,因此這不應是安全性問題。

隱私權注意事項

這項提案對隱私權應該不會有任何影響。

測試

這項功能需要單元和整合測試。一般測試區域如下:

  • 剖析新的 CML 語法。
  • 透過拓撲圖路由新能力。
  • 嘗試啟動缺少設定功能的元件。
  • 嘗試啟動具有錯誤類型設定能力的元件。
  • 啟動具備設定能力的動態元件。

這項功能需要在 Scrutiny 中新增下列測試:

  • 測試 Scrutiny 是否能解析設定功能的值。
  • 針對不同設定值來源測試優先順序/覆寫邏輯。
  • 測試設定功能、設定區塊和可變動性之間的互動。

這些測試都不需要新的測試基礎架構。

說明文件

您需要更新 Fuchsia.dev,才能取得設定功能的說明文件。現有的能力說明文件將做為這份新說明文件的範本。

缺點、替代方案和未知事項

替代做法:實作設定值覆寫服務

原始的 結構化設定 RFC 建議結構化設定直接取自元件的套件。RFC 特別指出,RFC 不會嘗試處理「由其他元件 (父項元件和管理員元件除外) 設定的設定資料」。另一個替代方案是繼續不支援以能力為基礎的設定配置。

使用設定功能而非覆寫服務的缺點之一,是設定功能較冗長且複雜。一開始在全球實作某項功能通常會比較簡單。不過,Fuchsia 發現,以能力為基礎的系統最終會變得更易於組合和理解。能夠指定特定組態只供元件拓樸結構的子集使用,或是在兩個不同的元件中使用兩個不同的值,這點非常實用。設定功能可讓您更輕鬆地表達並實現 Fuchsia 中其他地方使用的功能型系統。使用現有的 CML 語法進行設定,可讓 Fuchsia 開發人員更容易瞭解這項功能,而且與元件架構的現有工具搭配得宜。

缺點:需要使用許多額外的欄位

將類型資訊保留在 use 區塊中,會新增 6 個額外欄位,這些欄位僅適用於設定功能。

您可以將這 6 個欄位合併為一個包含子欄位的欄位,但建議您新增這些欄位,因為這樣可以讓語法與現有的 config 區塊語法保持一致。

缺點:混淆類型資訊和路由

將設定結構定義放入 use 宣告的缺點之一是,use 區塊會定義類型資訊,也會定義路由。有些元件可能會在不指定路由的情況下定義設定,然後在不同情況下以不同方式路由設定。如果類型資訊位於 Use 區塊以外的位置,這麼做會比較簡單。

元件作者如要變更類型定義方式,必須修改 use 區塊,而非只修改 config 區塊。

如果設定定義和路由的組合對開發人員來說是持續的痛點,元件架構團隊可能會重新考慮這項決定。

替代做法:在 config 區塊中保留設定類型定義

另一個替代做法是在 use 宣告中不包含「type」欄位,而是依賴現有「config」區塊中的類型資訊。這也是本 RFC 早期版本的情況。這個替代方案可解決將類型資訊和路由混淆的現有缺點。這樣一來,用戶端就能更輕鬆地在一個位置定義設定,並在其他位置進行路由 (可能包括不同的 CML 分片,以便根據不同的設定進行路由)。

在目前的結構化設定檔實作中,元件管理員會在啟動元件時「推送」設定檔,因此元件管理員需要確保已路由能力的類型與目標結構化設定檔欄位相符。我們決定將類型資訊放在 use 宣告中,因為這與功能宣告對稱。元件管理員執行路由時,需要確保類型資訊相符,也就是說,在邏輯上,資訊應包含在路徑的兩端 (能力和用途)。

use 宣告中保留類型資訊的另一個原因是,您可以將所有資訊保留在 use 宣告中,而不需要相符的「config」區塊項目。這樣一來,資訊就會儲存在 CML 檔案的單一位置,方便稽核。

替代做法:use 宣告中的 as 欄位

config 區塊中封裝結構化設定欄位名稱和類型資訊後,您可以使用 as 指定提供能力的欄位。這與 CML 中大多數非 path 的「重新命名」方式一致。

key 這個字詞會取代 as,因為這個欄位的運作方式與其他 as 欄位不同。as 通常為選用,但 key 則為必填。如果能力為選用,key 也必須與 config 區塊中的現有鍵相符。

未知:平衡現有結構化設定與功能的不一致性

現有的結構化設定與其他功能的運作方式不一致,這點有許多證據。

其中一個不一致之處是,程式會嚴重依賴元件資訊清單中定義的結構化設定格式。通常是資訊清單依賴程式,而結構化設定會讓這項關係形成循環。這可從以下事實看出:結構化設定建構規則需要在元件、元件資訊清單和程式之間新增額外層。設定功能不會解決這種循環不一致的情況,但希望在後續 RFC 中解決。

另一個不一致之處是,結構化設定會在元件啟動時「推送」至元件,而其他功能則會在元件存取時「拉取」。本 RFC 也未解決這項不一致性問題。這份 RFC 的目的是新增元件資訊清單中的轉送和能力支援。這項 RFC 不會變更程式和結構化設定之間的介面,因此所需的遷移次數有限。

在實作設定功能並瞭解其使用方式後,Fuchsia 將更能解決這些不一致的問題。客戶提供的資料越多,我們就能越有效地解決問題,並實施後續變更。

既有技術與參考資料

先前的結構化設定 rfc: