Bicep 配置继承是一项 bicepconfig.json 功能,它允许一个配置文件基于另一个配置文件进行扩展,而不是重复其内容。 配置文件继承了基础文件的设置,只覆盖需要更改的数值。
如果没有继承,每个需要 的 bicepconfig.json 文件夹都必须重述整个文件。 在仓库或组织中共享linter规则、模块别名或其他设置意味着要将整个配置复制到每个位置。 继承用一串小型、聚焦的配置文件链替代了这种重复。
例如,全公司范围的 bicepconfig.corp.json 可以为所有人定义严格的代码检查规则。 单个团队的 bicepconfig.json 会继承该文件,并禁用一条自己不需要的规则,而无需重述其他任何设置。
扩展属性如何继承配置
配置文件通过该 extends 属性继承另一个文件,该属性指向具有相对路径的基文件:
{
"extends": "../corp/bicepconfig.corp.json"
}
基础文件可以扩展另一个文件,因此配置可以形成多层的链条,比如团队文件扩展组织文件,再扩展企业文件。 Bicep 会按顺序解析这条链,从最具体的文件(叶节点)一直到最外层的基文件。
Bicep 对 extends 链的形状规定了几条规则:
| 约束 | Behavior | 诊断 |
|---|---|---|
| 路径类型 | 该 extends 值必须是相对路径,而非绝对路径。 |
BCP453 |
| 周期 | 链条无法形成循环。 Bicep 会拒绝扩展回其自身某个基文件的文件。 | BCP454 |
| 深度 | 一条链条最多可跨越64层。 Bicep 会拒绝超出该最大深度的链式结构。 | BCP455 |
如何应用全公司范围的继承
在此示例中,配置继承了基底的 no-unused-params 规则 as-is,同时将 no-hardcoded-env-urls 警告覆盖为错误。
// /shared/bicepconfig.base.json (shared org-wide base config)
{
"analyzers": {
"core": {
"rules": {
"no-hardcoded-env-urls": { "level" : "warning" },
"no-unused-params": { "level": "warning" }
}
}
}
}
// /team/bicepconfig.json (this team's leaf config - extends the shared base)
{
"extends" : "../shared/bicepconfig.base.json",
"analyzers": {
"core": {
"rules": {
"no-hardcoded-env-urls": { "level": "error" }
}
}
}
}
// Effective (merged) result:
{
"analyzers": {
"core": {
"rules": {
"no-hardcoded-env-urls": { "level": "error" }, // overridden by leaf
"no-unused-params": { "level": "warning" } // inherited from base, untouched
}
}
}
}
Bicep 如何合并继承的设置
Bicep 一键一键地合并extends链条,更具体的层获胜。 每个文件只需指定它想更改的键;任何未设置的内容都会从其基底中消失。 这种行为在每个配置部分都一致,比如分析器和衬条规则或模块别名。
一个值如何合并取决于其类型:
| 值类型 | 合并行为 |
|---|---|
| 对象 | 键以递归方式组合。 发生键冲突时,以更具体的文件为准,基础文件中的其他键则予以保留。 |
| Array | 已完全替换。 数组不会被追加、逐个元素合并或去重。 |
| 标量(字符串、数字、布尔值) | 完全被更具体的数值取代。 |
| Null | 异常。
null更具体文件中的值不会替代非空的基值;非空的基值依然存在。 |
值类型 null 是更具体的层不会胜出的唯一例外。 对于其他所有标量,更具体的值会替换基础值;但如果基础值为非 null 值,则会忽略叶文件中的 null,因此基础值仍然生效。
例如,如果基础文件将其设置为 "implicitExtensions": ["az", "k8s"],而更具体的文件将其设置为 "implicitExtensions": ["kubernetes"],则最终生效的值为 ["kubernetes"]。 基础数组被丢弃而非合并。
Bicep 如何发现配置文件
每个 Bicep 文件都独立解析其各自的配置。 从文件自身的文件夹开始,Bicep 沿着目录树向上移动,找到最近的 bicepconfig.json,然后沿着该文件的extends链条前进。 这种查找最近祖先的方式与没有继承时相同;继承只会增加一条从它找到的文件开始的链。
独立发现有两个重要影响:
- 本地模块解析各自的配置。 从父模板引用的模块不会继承父模板已经解析的设置。 它找到离自己最近的
bicepconfig.json,并沿着自己的链条继续。 两个文件在不同文件夹里,即使一个文件引用另一个,也可能有完全不同的有效设置。 -
.bicep文件和.bicepparam文件的行为相同。 位于某个扩展了共享基础配置的配置旁边的.bicepparam文件,会获得与该位置的.bicep文件相同的多层链和合并行为。
因为共享基文件可以位于多个链的顶部,对该基的编辑会传播到所有扩展它的配置,包括链更下游的传递依赖变量。 Bicep 只会更新依赖于已更改文件的依赖链,因此你可以在受影响的文件上看到最新的生效设置,而不会触发对工作区中所有配置的完整重建。
在继承的 bicepconfig.json 设置中如何解析相对路径
有些设置包含相对路径,比如指向本地文件夹的模块别名。 当文件继承了这样的设置时,它的相对路径会相对于声明该设置的文件进行解析,而不是相对于通过 extends 将其引入的叶子配置文件进行解析。
考虑一个定义模块别名路径为的 ../modules基础文件:
/apps/bicepconfig.json extends ../config/bicepconfig.base.json
/config/bicepconfig.base.json defines alias "shared" -> ../modules
shared 别名相对于 /config/ 进行解析,因此指向 /modules。 即使叶片配置是别名生效的地方,它也不会相对于 /apps/分辨。 按声明文件进行解析这一规则无论链有多深都成立:相对路径始终相对于声明它的文件进行解析,无论该文件是直接基文件,还是向上追溯几层的基文件。 该规则使共享的基础配置能够保持可移植性,因为无论哪个文件继承它们,别名和其他相对路径表示的含义都相同。
设置配置继承
通过简短的设置,把配置继承付诸实践:定义一个共享的基文件,从更具体的文件扩展,只覆盖你需要的部分。 这些步骤构建了一个两层链式结构,其中企业级基础配置强制实施一条 linter 规则,而团队配置文件则将该规则关闭。
创建基础配置文件。 在共享文件夹中,添加一个
bicepconfig.json,用于定义每个文件都应继承的设置。 这个例子在组织内强制执行“linter rule”。{ "analyzers": { "core": { "rules": { "no-hardcoded-env-urls": { "level": "error" } } } } }引用更具体文件中的基础文件。 在需要使用不同设置的文件夹中,添加一个带有
extends属性的bicepconfig.json,该属性通过相对路径指向基础文件。{ "extends": "../corp/bicepconfig.json" }只覆盖你需要的设置。 把你想更改的密钥添加到更具体的文件里。 凡是你省略的内容,都会继续从基底层漏下去。 该文件关闭继承规则,但不重复配置的其他部分。
{ "extends": "../corp/bicepconfig.json", "analyzers": { "core": { "rules": { "no-hardcoded-env-urls": { "level": "off" } } } } }如果需要,可以多加几层。 基础文件可以扩展自己的基础文件,所以你可以在公司文件和团队文件之间插入一个组织文件。 每层只覆盖其关心的密钥,最高可达64层上限。
验证有效配置。 在包含更具体配置的文件夹里打开一个
.bicep文件。 被覆盖的规则在那里不再适用,而解析到基站的文件仍然执行该规则。 编辑基础文件,确认更改会传播到依赖文件,无需重建。 确认该链中的任何文件上均未出现BCP453、BCP454或BCP455诊断。
在验证这些结果后,团队文件夹会继承除其覆盖的那条规则外的所有企业设置,并且你只需在一处维护这套共享基线,而不必将其复制到每个文件夹中。
排查 bicepconfig.json 继承问题
当 extends 链中的任何文件出现问题时,Bicep 都会停止解析整个链,因此无法将编辑器中的波浪线提示定位或路由到有问题的配置文件。 由于解析会立即停止,因此诊断信息及其在编辑器中的波浪线标记会显示在你当前正在评估或已打开的文档上——即 .bicep 或 .bicepparam 源文件,或者你直接打开的 bicepconfig.json——而不一定显示在导致该问题的配置文件上。
诊断 消息 用于识别问题文件。 Bicep 在诊断中包含了文件路径,因此即使波浪线出现在另一个文件上,消息文本仍指向问题的实际来源。 通过阅读消息来找到需要修复的文件,而不要想当然地认为波浪线标出的就是它。
最常见的继承问题与以下诊断结果相符:
| 诊断 | 原因 |
|---|---|
BCP453 |
extends 路径是绝对路径。 改用相对路径。 |
BCP454 |
链条形成一个循环。 移除指向链条的参考点 extends 。 |
BCP455 |
链条太深了。 减少层数,使链条保持在64层最大范围内。 |
UnloadableBicepConfigFile |
extends目标不存在或无法读取。 纠正相对路径或恢复缺失的文件。 |
UnparsableBicepConfigFile |
链中的一个文件包含格式错误的 JSON。 修正报告文件中的JSON语法。 |
BCP453、BCP454 和 BCP455 诊断特定于 extends 链。
UnloadableBicepConfigFile和 UnparsableBicepConfigFile 诊断适用于任何bicepconfig.json文件,但当它们发生在基文件时也会破坏继承:不可读取的目标会阻止链的加载,而任何层的 JSON 格式错误会阻止 Bicep 解析该层。 在每种情况下,诊断信息都会指出问题所在的文件,尽管你当前打开的文档上会出现波浪形。