上下文:我正在开发一个TF提供程序,并学习HashiCorp的教程。
我正试图想出一个资源定义,但不知道该选择哪一个。
- 选项#1:
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"endpoint": {
Type: schema.TypeString,
Required: true,
},
},
resource "foo" "bar" {
name = "alex"
endpoint = "https://api.stripe.com" # unique for every bar
}
- 选项#2:
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"district_id": {
Type: schema.TypeString,
Required: true,
},
},
resource "foo" "bar" {
name = "alex"
district_id = "NE53DE" # unique for every bar
}
#1的优点是它遵循API,并且为了执行CRUD操作,TF提供程序只能与一个API组交互(API组和资源之间有1:1的映射(。
#2的优点是它更具可读性,但为了调用API组#1,我们仍然需要找出端点,因此TF提供程序必须调用API组#2来检索该端点。
在开发TF提供商时,这些选项中的哪一个更常用?
不幸的是,您在这里讨论的可能是Terraform提供商开发中最关键的部分:就如何最好地将Terraform的提供商无关生命周期模型转化为特定真实API的物理约束进行权衡和判断。
密切遵循远程API设计的一大优势是,未来扩展到API设计会使您的提供商设计无效的可能性较小。如果提供者是由不直接与设计API的团队合作的人设计的,这一点可能尤为重要,因为提供者开发人员通常无法预测API未来可能会发生什么变化,以及API设计团队在考虑新的用例时通常遵循什么设计原则。
然而,正如您所注意到的,真实世界的API通常不是为了方便直接使用而设计的,而是为了暴露原始构建块,假设其他人会在上面构建适当的用例特定的抽象。Terraform提供程序的开发人员最终会遇到一些困难,因为他们通常也试图提供一个通用的解决方案(而不是专注于特定的用例(,但也想设计一些在Terraform语言中使用相对方便的东西。
我无法提供具体的建议,因为我对您为之设计的API或您为提供商设计的目标没有足够的背景,但我至少可以提供一个潜在的妥协机会:数据源。
除了表示Terraform直接管理远程系统中某个对象的托管资源类型外,Terraform还支持数据资源类型(简称"数据源"(,这些类型在Terraform语言中显示为data
块。这些本质上是对特定模块的外部依赖项进行建模,我所说的对象是指模块希望其他人已经创建的对象,以及模块需要声明其自己将管理的对象(其管理的资源(的对象。
如果您从";地区ID";至";端点";在某种意义上可以被认为是一个外部对象,那么数据源可以帮助填补这一空白。不要太担心它是否真的是远程系统中的一级对象;这里重要的是Terraform模块作者将其视为一个模块是否合理,这样他们就可以代表您的";找出端点";作为数据资源的需求:
data "foo_district_endpoint" "example" {
district_id = "NE53DE"
}
resource "foo" "bar" {
name = "alex"
endpoint = data.foo_district_endpoint.example.endpoint
}
然后,这就明确了您所描述的发出API请求以根据地区ID确定端点的需求,而不是将其隐藏为foo
的实现细节。明确它的一个重要优点是,查找它的模块可能并不总是使用它的模块;对于使用模块组合模式的配置,这两种需求可能会被拆分为两个较小的模块,因此endpoint
值将使用输出值和输入变量从一个模块流到另一个模块。
你描述的两种可能性和我添加的第三种可能性都是针对不同情况的有效和可辩护的设计。虽然我不能告诉你哪一个最适合你的具体情况,但我希望这条评论至少有助于你考虑一些事情,帮助你自己做出决定。