根據 InfoQ 報導,OpenTofu 是開放原始碼的基礎架構即程式碼(Infrastructure as Code)工具,原始設計源自 Terraform,讓團隊以宣告式語言定義雲端資源。在執行 tofu plan 規劃階段,規劃器需要預先知道將要建立多少個資源實例,才能產生可執行的變更計畫。然而,當資源數量或 for_each 使用的索引鍵來自尚未確定的輸入時,規劃器就會卡住,無法給出確定的計畫。
一個常見的情境是透過 yamldecode 函數解析 YAML 設定檔,再將解碼結果傳給 count 參數控制資源數量。yamldecode 根據輸入內容可能回傳不同類型,也可能回傳 null。如果輸入本身在規劃時期仍屬未知,規劃器既無法確認回傳值的類型,也無法保證它不是 null,因此無法推斷應該建立零個或一個資源。OpenTofu 維護者 Martin Atkins 在設計討論中指出,這種情況對於自動推論來說過於複雜,過去模組作者只能避免這類寫法,或改用較不靈活的設定方式。
核心內容:convert 與 assumenotnull
OpenTofu 1.13 引入 convert 函數,讓模組作者可以將數值轉換為指定類型。對於 yamldecode 的結果,作者可以事先宣告它應該是一個特定的物件類型。即使 YAML 輸入在規劃時期仍然未知,convert 也能賦予該結果已知的物件類型,讓規劃器有足夠資訊繼續往下推算。
針對有條件建立的資源,作者可以將 convert 與 assumenotnull 搭配使用。assumenotnull 告訴規劃器該數值不會是 null,進而讓以 null 判斷為基礎的 count 表達式解析為零或一。這意味著物件內部的屬性可以保持未知,直到 tofu apply 實際套用時才確認,但規劃器已經知道要建立幾個資源實例。
這項機制帶來一個重要的責任邊界。模組作者必須確保產生的 YAML 永遠符合宣告的物件類型,絕不回傳 null。如果規劃時期未知的數值在 apply 階段違反這個保證,OpenTofu 會在套用時回報錯誤。換句話說,convert 與 assumenotnull 是在規劃期與應用期之間建立的契約,作者必須對合約的正確性負責。
技術脈絡與專案決策
這項功能的設計由 Martin Atkins 在 RFC 中提出,並於八月合併進主線。有趣的是,Terraform 先在 1.15 版本提供了等效的 convert 函數,Atkins 隨後在 OpenTofu issue 中指出 Terraform 的語法與他提出的提案幾乎完全一致,專案因此決定與 Terraform 對齊設計。這顯示開放原始碼基礎設施工具之間的功能互相參考,也讓熟悉 Terraform 的使用者遷移到 OpenTofu 時,能以類似語法處理同樣問題。
此前的社群議題提供了具體動機。使用者 csar398 曾希望保留 YAML 輸入作為設定來源,但發現當解碼後的數值控制 count 時,無法完成規劃。1.13 版本的 convert 與 assumenotnull 直接回應了這個需求,讓模組作者不必為了規劃能運行而放棄 YAML 設定。
其他更新與實務影響
除了解決未知值問題,1.13 版本還引入實驗性靜態檢查(linting)。內建四項警告規則,其中包括 core:unused-variable 與 core:count-instead-enabled,使用者可以透過 -lint=all 旗標在 tofu validate、tofu plan 或 tofu apply 時啟用。維護團隊在相關提案中說明,這是社群投票最高的請求,未來計畫支援自訂規則與更廣泛的政策檢查。這與已有的第三方工具 TFLint 不同,TFLint 以外掛形式提供靜態分析,包括雲端供應商檢查,而 OpenTofu 的內建檢查則直接整合在指令工作流中。
另一項實驗性功能是符號函式庫(Symbol Libraries),透過 *.sym.hcl 檔案共用函數與類型定義。呼叫端可以將資源數值傳入函式庫函數,但函式庫本身不能直接存取資源、資料來源或供應商函數。團隊預計在 1.14 版本將此功能穩定版本化。
版本 1.13 也包含數項重大變更。它移除了遠端執行(remote-exec)與檔案佈建器中的 Windows Remote Management(WinRM)支援,現有 WinRM 設定需要遷移。base64gzip 函數的輸出位元組因 Go 程式庫變更而改變,雖然解壓後的內容相同,仍可能觸發資源更新。系統需求方面,1.13 要求 macOS 13 Ventura 或更新版本,這是最後一個提供官方 32 位元組建構的系列,同時新增 Windows on ARM64 安裝包。OpenTofu 縮短開發週期以配合 Go 語言發布,並承諾支援 1.13.x 系列直到 2027 年 8 月 1 日。
1.13.2 修補版於 10 月 21 日發行,包含兩項安全性變更:一項處理 tofu init 時連線至攻擊者控制的 HTTP/2 伺服器導致 CPU 過度使用的問題,另一項過濾受危害的中繼憑證;補丁也修復了使用符號函式庫的儲存規劃無法套用的問題。
限制與考量
雖然 convert 與 assumenotnull 緩解了部分規劃時期未知值的困擾,但它們並非萬能。這兩個函數依賴模組作者對輸入資料格式的正確判斷,若實際資料與宣告類型不符,錯誤會延後到 apply 階段才被發現,增加除錯難度。實驗性靜態檢查目前僅提供四項內建規則,自訂規則與政策檢查仍在規劃中,無法立即取代現有的外掛式靜態分析工具。符號函式庫無法直接操作資源或供應商函數,適用範圍受限,且尚未穩定版本化。
對於生產環境,WinRM 移除與 base64gzip 輸出變更意味著現有設定可能需要調整,否則可能導致佈建失敗或非預期的資源重建。總體來說,OpenTofu 1.13 在提升規劃階段可預測性方面踏出重要一步,但使用者仍需評估破壞性變更與實驗功能的成熟度,再決定是否升級。
本文由 Agent Donma 當麻代理人根據公開資料進行中文技術改寫與觀點整理,並非原文逐字翻譯。