自定义Terraform-Providers(Terraform Plugin Framework)-04
一 前言
Terraform插件框架是开发Terraform插件的一种新方法。它具有Terraform插件SDKv2所缺少的特性,包括:
- 确定是否在配置、状态或计划中设置了值。
- 确定值是null、未知还是空值。
- 具有结构化类型,如对象。
- 本机使用嵌套属性。
在本教程中,您将使用Terraform插件框架,为一个虚构的咖啡店应用程序(HashiCups)的提供程序添加创建和读取功能。首先,您将回顾provider和resource schema,以了解provider如何使用插件框架将Go结构映射到schema属性。然后,在自己实现资源之前,您将探索与创建和读取资源相关联的步骤。最后,您将测试提供程序。
HashiCups API有不受保护的端点,允许您列出特定咖啡的所有咖啡和成分。经过身份验证后,可以创建、读取、更新和删除(CRUD)订单。HashiCups提供程序通过GoLang客户机库与HashiCups REST API接口。这允许您通过Terraform管理HashiCups订单。
这个框架是实验性的。不要在生产或关键环境中使用。在Terraform插件框架Github存储库中向开发团队提交任何问题。有关反馈和讨论,请访问插件SDK讨论论坛。
二 预置条件
对于本教程,您将需要:
- 安装并配置Go1.16+。的
- Terraform V1.0.3+已在本地安装。
- Docker和Docker组合在本地运行HashiCups实例。
- 安装了jq。
三 配置开发环境
git clone --branch boilerplate https://github.com/hashicorp/terraform-provider-hashicups-pf
cd terraform-provider-hashicups-pf
四 启动项目
cd docker_compose
docker-compose up -d
curl localhost:19090/health
五 创建用户
$ curl -X POST localhost:19090/signup -d '{"username":"education", "password":"test123"}'
{"UserID":1,"Username":"education","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NTQ4MjU4ODYsInVzZXJfaWQiOjEsInVzZXJuYW1lIjoiZWR1Y2F0aW9uIn0.DD1LxrJJL05wKJ56f8FSm-lerdBvyCYaUZCnJM4m4AY"}
$ export HASHICUPS_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NTQ4MjU4ODYsInVzZXJfaWQiOjEsInVzZXJuYW1lIjoiZWR1Y2F0aW9uIn0.DD1LxrJJL05wKJ56f8FSm-lerdBvyCYaUZCnJM4m4AY
六 开发HashiCups provider
main.go文件
package main
import (
"context"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"terraform-provider-hashicups/hashicups"
)
func main() {
tfsdk.Serve(context.Background(), hashicups.New, tfsdk.ServeOpts{
Name: "hashicups",
})
}
打开hashicups/provider.go。
首先,提供程序调用新函数来调用提供程序的实例。请注意,该文件还定义了一个带有客户端的提供程序结构。像SDKv2一样,Terraform提供程序应该与API客户机接口,而不是直接向API提交请求。
package hashicups
import (
"context"
"os"
"github.com/hashicorp-demoapp/hashicups-client-go"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
)
var stderr = os.Stderr
func New() tfsdk.Provider {
return &provider{}
}
type provider struct {
configured bool
client *hashicups.Client
}
接下来,提供程序定义一个模式,Terraform将使用该模式来配置HashiCups API客户机。providerData结构将这些模式属性映射到易于访问的值。
hashicups/provider.go
// GetSchema
func (p *provider) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnostics) {
return tfsdk.Schema{
Attributes: map[string]tfsdk.Attribute{
"host": {
Type: types.StringType,
Optional: true,
Computed: true,
},
"username": {
Type: types.StringType,
Optional: true,
Computed: true,
},
"password": {
Type: types.StringType,
Optional: true,
Computed: true,
Sensitive: true,
},
},
}, nil
}
// Provider schema struct
type providerData struct {
Username types.String `tfsdk:"username"`
Host types.String `tfsdk:"host"`
Password types.String `tfsdk:"password"`
}
6.1 定义资源和数据源
GetResources和GetDataSources函数定义提供者的资源和数据源。HashiCups提供程序的这个样板版本有一个名为HashiCups\u order的资源,不定义任何数据源。
// GetResources - Defines provider resources
func (p *provider) GetResources(_ context.Context) (map[string]tfsdk.ResourceType, diag.Diagnostics) {
return map[string]tfsdk.ResourceType{
"hashicups_order": resourceOrderType{},
}, nil
}
// GetDataSources - Defines provider data sources
func (p *provider) GetDataSources(_ context.Context) (map[string]tfsdk.DataSourceType, diag.Diagnostics) {
return map[string]tfsdk.DataSourceType{}, nil
}
6.2 查看Review HashiCups models
package hashicups
import (
"github.com/hashicorp/terraform-plugin-framework/types"
)
// Order -
type Order struct {
ID types.String `tfsdk:"id"`
Items []OrderItem `tfsdk:"items"`
LastUpdated types.String `tfsdk:"last_updated"`
}
// OrderItem -
type OrderItem struct {
Coffee Coffee `tfsdk:"coffee"`
Quantity int `tfsdk:"quantity"`
}
// Coffee -
// This Coffee struct is for Order.Items[].Coffee which does not have an
// ingredients field in the schema defined by plugin framework. Since the
// resource schema must match the struct exactly (extra field will return an
// error). This struct has Ingredients commented out.
type Coffee struct {
ID int `tfsdk:"id"`
Name types.String `tfsdk:"name"`
Teaser types.String `tfsdk:"teaser"`
Description types.String `tfsdk:"description"`
Price types.Number `tfsdk:"price"`
Image types.String `tfsdk:"image"`
// Ingredients []Ingredient `tfsdk:"ingredients"`
}
// Ingredient -
// type Ingredient struct {
// ID int `tfsdk:"ingredient_id"`
// Name string `tfsdk:"name"`
// Quantity int `tfsdk:"quantity"`
// Unit string `tfsdk:"unit"`
// }
6.3 实现具体方法
6.2.1 创建方法
- 检查是否配置了提供程序和API客户端。如果不是,提供程序将以错误响应。
- 从计划中检索值。该函数将尝试从计划中检索值,并将其转换为Order结构(在models.go中定义)。
- 从计划值生成API请求正文。该函数循环遍历每个计划项,并将其映射到HashiCups.OrderItem。这就是API客户机创建新订单所需要的。
- 创建新订单。该函数调用API客户端的CreateOrder方法。
- 将响应正文映射到资源架构属性。函数创建订单后,它将HashiCups.order响应映射到[]OrderItem,这样提供者就可以更新Terraform状态。
- 将状态设置为新顺序。
6.2.2 读取方法
- 获取当前状态。如果不能,则提供程序将以错误进行响应。
- 从状态检索订单ID。
- 获取订单的信息。该函数使用订单ID调用API客户机的GetOrder方法。
- 将响应正文映射到资源架构属性。函数检索订单后,它将HashiCups.order响应映射到[]OrderItem,这样提供者就可以更新Terraform状态。
- 将状态设置为新顺序。
七 执行构建
go env GOBIN
创建文件
provider_installation {
dev_overrides {
"hashicorp.com/edu/hashicups-pf" = "<PATH>"
}
# For all other providers, install them directly from their origin provider
# registries as normal. If you omit this, Terraform will _only_ use
# the dev_overrides block, and so no other providers will be available.
direct {}
}
go mod tidy
go install
参考链接
- 点赞
- 收藏
- 关注作者
评论(0)