provider-resources by hashicorp/agent-skills
npx skills add https://github.com/hashicorp/agent-skills --skill provider-resources本指南涵盖使用 Terraform Plugin Framework 开发 Terraform Provider 资源和数据源。资源代表 Terraform 通过创建、读取、更新和删除(CRUD)操作管理的基础设施对象。
参考资料:
资源遵循标准的服务包结构:
internal/service/<service>/
├── <resource_name>.go # 资源实现
├── <resource_name>_test.go # 验收测试
├── <resource_name>_data_source.go # 数据源(如适用)
├── find.go # 查找函数
├── exports_test.go # 测试导出
└── service_package_gen.go # 自动生成的注册
文档结构:
website/docs/r/
└── <service>_<resource_name>.html.markdown # 资源文档
website/docs/d/
└── <service>_<resource_name>.html.markdown # 数据源文档
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
func ResourceExample() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceExampleCreate,
ReadWithoutTimeout: resourceExampleRead,
UpdateWithoutTimeout: resourceExampleUpdate,
DeleteWithoutTimeout: resourceExampleDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringLenBetween(1, 255),
},
"arn": {
Type: schema.TypeString,
Computed: true,
},
"tags": tftags.TagsSchema(),
"tags_all": tftags.TagsSchemaComputed(),
},
CustomizeDiff: verify.SetTagsDiff,
}
}
type resourceExample struct {
framework.ResourceWithConfigure
}
func (r *resourceExample) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_example"
}
func (r *resourceExample) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"id": framework.IDAttribute(),
"name": schema.StringAttribute{
Required: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
Validators: []validator.String{
stringvalidator.LengthBetween(1, 255),
},
},
"arn": schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
},
}
}
func (r *resourceExample) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data resourceExampleModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
conn := r.Meta().ExampleClient(ctx)
input := &example.CreateExampleInput{
Name: data.Name.ValueStringPointer(),
}
output, err := conn.CreateExample(ctx, input)
if err != nil {
resp.Diagnostics.AddError(
"创建 Example 时出错",
fmt.Sprintf("无法创建示例 %s: %s", data.Name.ValueString(), err),
)
return
}
data.ID = types.StringPointerValue(output.Id)
data.ARN = types.StringPointerValue(output.Arn)
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
func (r *resourceExample) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var data resourceExampleModel
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
conn := r.Meta().ExampleClient(ctx)
output, err := findExampleByID(ctx, conn, data.ID.ValueString())
if tfresource.NotFound(err) {
resp.Diagnostics.AddWarning(
"资源未找到",
fmt.Sprintf("未找到示例 %s,正在从状态中移除", data.ID.ValueString()),
)
resp.State.RemoveResource(ctx)
return
}
if err != nil {
resp.Diagnostics.AddError(
"读取 Example 时出错",
fmt.Sprintf("无法读取示例 %s: %s", data.ID.ValueString(), err),
)
return
}
data.Name = types.StringPointerValue(output.Name)
data.ARN = types.StringPointerValue(output.Arn)
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
func (r *resourceExample) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var plan, state resourceExampleModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}
conn := r.Meta().ExampleClient(ctx)
if !plan.Description.Equal(state.Description) {
input := &example.UpdateExampleInput{
Id: plan.ID.ValueStringPointer(),
Description: plan.Description.ValueStringPointer(),
}
_, err := conn.UpdateExample(ctx, input)
if err != nil {
resp.Diagnostics.AddError(
"更新 Example 时出错",
fmt.Sprintf("无法更新示例 %s: %s", plan.ID.ValueString(), err),
)
return
}
}
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
}
func (r *resourceExample) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var data resourceExampleModel
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
conn := r.Meta().ExampleClient(ctx)
_, err := conn.DeleteExample(ctx, &example.DeleteExampleInput{
Id: data.ID.ValueStringPointer(),
})
if tfresource.NotFound(err) {
return
}
if err != nil {
resp.Diagnostics.AddError(
"删除 Example 时出错",
fmt.Sprintf("无法删除示例 %s: %s", data.ID.ValueString(), err),
)
return
}
}
| Terraform 类型 | Framework 类型 | 使用场景 |
|---|---|---|
string | schema.StringAttribute | 名称、ARN、ID |
number | schema.Int64Attribute, schema.Float64Attribute | 计数、大小 |
bool | schema.BoolAttribute | 功能开关 |
list | schema.ListAttribute | 有序集合 |
set | schema.SetAttribute | 无序唯一项 |
map | schema.MapAttribute | 键值对 |
object | schema.SingleNestedAttribute | 复杂嵌套配置 |
// 值更改时强制替换
stringplanmodifier.RequiresReplace()
// 在计划期间保留未知值
stringplanmodifier.UseStateForUnknown()
// 自定义计划修改器
stringplanmodifier.RequiresReplaceIf(
func(ctx context.Context, req planmodifier.StringRequest, resp *stringplanmodifier.RequiresReplaceIfFuncResponse) {
// 自定义逻辑
},
"description",
"markdown description",
)
// 字符串验证器
stringvalidator.LengthBetween(1, 255)
stringvalidator.RegexMatches(regexp.MustCompile(`^[a-z0-9-]+$`), "必须为小写字母数字加连字符")
stringvalidator.OneOf("option1", "option2", "option3")
// Int64 验证器
int64validator.Between(1, 100)
int64validator.AtLeast(1)
int64validator.AtMost(1000)
// 列表验证器
listvalidator.SizeAtLeast(1)
listvalidator.SizeAtMost(10)
"password": schema.StringAttribute{
Required: true,
Sensitive: true,
Validators: []validator.String{
stringvalidator.LengthAtLeast(8),
},
}
func findExampleByID(ctx context.Context, conn *example.Client, id string) (*example.Example, error) {
input := &example.GetExampleInput{
Id: &id,
}
output, err := conn.GetExample(ctx, input)
if err != nil {
var notFound *types.ResourceNotFoundException
if errors.As(err, ¬Found) {
return nil, &retry.NotFoundError{
LastError: err,
LastRequest: input,
}
}
return nil, err
}
if output == nil || output.Example == nil {
return nil, tfresource.NewEmptyResultError(input)
}
return output.Example, nil
}
func waitExampleCreated(ctx context.Context, conn *example.Client, id string, timeout time.Duration) (*example.Example, error) {
stateConf := &retry.StateChangeConf{
Pending: []string{"CREATING", "PENDING"},
Target: []string{"ACTIVE", "AVAILABLE"},
Refresh: statusExample(ctx, conn, id),
Timeout: timeout,
}
outputRaw, err := stateConf.WaitForStateContext(ctx)
if output, ok := outputRaw.(*example.Example); ok {
return output, err
}
return nil, err
}
func statusExample(ctx context.Context, conn *example.Client, id string) retry.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := findExampleByID(ctx, conn, id)
if tfresource.NotFound(err) {
return nil, "", nil
}
if err != nil {
return nil, "", err
}
return output, string(output.Status), nil
}
}
func TestAccExampleResource_basic(t *testing.T) {
ctx := acctest.Context(t)
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "provider_example.test"
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckExampleDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccExampleConfig_basic(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckExampleExists(ctx, resourceName),
resource.TestCheckResourceAttr(resourceName, "name", rName),
resource.TestCheckResourceAttrSet(resourceName, "arn"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccExampleResource_disappears(t *testing.T) {
ctx := acctest.Context(t)
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "provider_example.test"
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckExampleDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccExampleConfig_basic(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckExampleExists(ctx, resourceName),
acctest.CheckResourceDisappears(ctx, acctest.Provider, ResourceExample(), resourceName),
),
ExpectNonEmptyPlan: true,
},
},
})
}
func testAccCheckExampleExists(ctx context.Context, name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("未找到: %s", name)
}
conn := acctest.Provider.Meta().(*conns.Client).ExampleClient(ctx)
_, err := findExampleByID(ctx, conn, rs.Primary.ID)
return err
}
}
func testAccCheckExampleDestroy(ctx context.Context) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.Client).ExampleClient(ctx)
for _, rs := range s.RootModule().Resources {
if rs.Type != "provider_example" {
continue
}
_, err := findExampleByID(ctx, conn, rs.Primary.ID)
if tfresource.NotFound(err) {
continue
}
if err != nil {
return err
}
return fmt.Errorf("示例 %s 仍然存在", rs.Primary.ID)
}
return nil
}
}
# 编译测试
go test -c -o /dev/null ./internal/service/<service>
# 运行验收测试
TF_ACC=1 go test ./internal/service/<service> -run TestAccExample -v -timeout 60m
# 使用特定 Provider 版本运行
TF_ACC=1 go test ./internal/service/<service> -run TestAccExample -v
# 运行清理器进行清理
TF_ACC=1 go test ./internal/service/<service> -sweep=<region> -v
// 处理特定 API 错误
var notFound *types.ResourceNotFoundException
if errors.As(err, ¬Found) {
// 资源不存在
}
var conflict *types.ConflictException
if errors.As(err, &conflict) {
// 资源状态冲突
}
var throttle *types.ThrottlingException
if errors.As(err, &throttle) {
// 速率限制 - SDK 处理重试
}
// 添加错误
resp.Diagnostics.AddError(
"创建资源时出错",
fmt.Sprintf("无法创建资源: %s", err),
)
// 添加警告
resp.Diagnostics.AddWarning(
"资源在 Terraform 外部被修改",
"资源在 Terraform 外部被修改,状态可能不一致",
)
// 添加属性错误
resp.Diagnostics.AddAttributeError(
path.Root("name"),
"名称无效",
"名称必须为小写字母数字",
)
---
subcategory: "服务名称"
layout: "provider"
page_title: "Provider: provider_example"
description: |-
管理 Example 资源。
---
# Resource: provider_example
管理 Example 资源。
## 示例用法
### 基础用法
\```hcl
resource "provider_example" "example" {
name = "my-example"
}
\```
## 参数参考
* `name` - (必需)示例的名称。
* `description` - (可选)示例的描述。
## 属性参考
* `id` - 示例的 ID。
* `arn` - 示例的 ARN。
## 导入
可以使用 ID 导入 Example:
\```
$ terraform import provider_example.example example-id-12345
\```
每周安装次数
689
仓库
GitHub 星标数
481
首次出现
2026年1月26日
安全审计
安装于
github-copilot571
opencode558
codex549
gemini-cli543
amp483
kimi-cli482
This guide covers developing Terraform Provider resources and data sources using the Terraform Plugin Framework. Resources represent infrastructure objects that Terraform manages through Create, Read, Update, and Delete (CRUD) operations.
References:
Resources follow the standard service package structure:
internal/service/<service>/
├── <resource_name>.go # Resource implementation
├── <resource_name>_test.go # Acceptance tests
├── <resource_name>_data_source.go # Data source (if applicable)
├── find.go # Finder functions
├── exports_test.go # Test exports
└── service_package_gen.go # Auto-generated registration
Documentation structure:
website/docs/r/
└── <service>_<resource_name>.html.markdown # Resource documentation
website/docs/d/
└── <service>_<resource_name>.html.markdown # Data source documentation
func ResourceExample() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceExampleCreate,
ReadWithoutTimeout: resourceExampleRead,
UpdateWithoutTimeout: resourceExampleUpdate,
DeleteWithoutTimeout: resourceExampleDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringLenBetween(1, 255),
},
"arn": {
Type: schema.TypeString,
Computed: true,
},
"tags": tftags.TagsSchema(),
"tags_all": tftags.TagsSchemaComputed(),
},
CustomizeDiff: verify.SetTagsDiff,
}
}
type resourceExample struct {
framework.ResourceWithConfigure
}
func (r *resourceExample) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_example"
}
func (r *resourceExample) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"id": framework.IDAttribute(),
"name": schema.StringAttribute{
Required: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
Validators: []validator.String{
stringvalidator.LengthBetween(1, 255),
},
},
"arn": schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
},
}
}
func (r *resourceExample) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data resourceExampleModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
conn := r.Meta().ExampleClient(ctx)
input := &example.CreateExampleInput{
Name: data.Name.ValueStringPointer(),
}
output, err := conn.CreateExample(ctx, input)
if err != nil {
resp.Diagnostics.AddError(
"Error creating Example",
fmt.Sprintf("Could not create example %s: %s", data.Name.ValueString(), err),
)
return
}
data.ID = types.StringPointerValue(output.Id)
data.ARN = types.StringPointerValue(output.Arn)
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
func (r *resourceExample) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var data resourceExampleModel
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
conn := r.Meta().ExampleClient(ctx)
output, err := findExampleByID(ctx, conn, data.ID.ValueString())
if tfresource.NotFound(err) {
resp.Diagnostics.AddWarning(
"Resource not found",
fmt.Sprintf("Example %s not found, removing from state", data.ID.ValueString()),
)
resp.State.RemoveResource(ctx)
return
}
if err != nil {
resp.Diagnostics.AddError(
"Error reading Example",
fmt.Sprintf("Could not read example %s: %s", data.ID.ValueString(), err),
)
return
}
data.Name = types.StringPointerValue(output.Name)
data.ARN = types.StringPointerValue(output.Arn)
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
func (r *resourceExample) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var plan, state resourceExampleModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}
conn := r.Meta().ExampleClient(ctx)
if !plan.Description.Equal(state.Description) {
input := &example.UpdateExampleInput{
Id: plan.ID.ValueStringPointer(),
Description: plan.Description.ValueStringPointer(),
}
_, err := conn.UpdateExample(ctx, input)
if err != nil {
resp.Diagnostics.AddError(
"Error updating Example",
fmt.Sprintf("Could not update example %s: %s", plan.ID.ValueString(), err),
)
return
}
}
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
}
func (r *resourceExample) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var data resourceExampleModel
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
conn := r.Meta().ExampleClient(ctx)
_, err := conn.DeleteExample(ctx, &example.DeleteExampleInput{
Id: data.ID.ValueStringPointer(),
})
if tfresource.NotFound(err) {
return
}
if err != nil {
resp.Diagnostics.AddError(
"Error deleting Example",
fmt.Sprintf("Could not delete example %s: %s", data.ID.ValueString(), err),
)
return
}
}
| Terraform Type | Framework Type | Use Case |
|---|---|---|
string | schema.StringAttribute | Names, ARNs, IDs |
number | schema.Int64Attribute, schema.Float64Attribute | Counts, sizes |
bool | schema.BoolAttribute | Feature flags |
// Force replacement when value changes
stringplanmodifier.RequiresReplace()
// Preserve unknown value during plan
stringplanmodifier.UseStateForUnknown()
// Custom plan modifier
stringplanmodifier.RequiresReplaceIf(
func(ctx context.Context, req planmodifier.StringRequest, resp *stringplanmodifier.RequiresReplaceIfFuncResponse) {
// Custom logic
},
"description",
"markdown description",
)
// String validators
stringvalidator.LengthBetween(1, 255)
stringvalidator.RegexMatches(regexp.MustCompile(`^[a-z0-9-]+$`), "must be lowercase alphanumeric with hyphens")
stringvalidator.OneOf("option1", "option2", "option3")
// Int64 validators
int64validator.Between(1, 100)
int64validator.AtLeast(1)
int64validator.AtMost(1000)
// List validators
listvalidator.SizeAtLeast(1)
listvalidator.SizeAtMost(10)
"password": schema.StringAttribute{
Required: true,
Sensitive: true,
Validators: []validator.String{
stringvalidator.LengthAtLeast(8),
},
}
func findExampleByID(ctx context.Context, conn *example.Client, id string) (*example.Example, error) {
input := &example.GetExampleInput{
Id: &id,
}
output, err := conn.GetExample(ctx, input)
if err != nil {
var notFound *types.ResourceNotFoundException
if errors.As(err, ¬Found) {
return nil, &retry.NotFoundError{
LastError: err,
LastRequest: input,
}
}
return nil, err
}
if output == nil || output.Example == nil {
return nil, tfresource.NewEmptyResultError(input)
}
return output.Example, nil
}
func waitExampleCreated(ctx context.Context, conn *example.Client, id string, timeout time.Duration) (*example.Example, error) {
stateConf := &retry.StateChangeConf{
Pending: []string{"CREATING", "PENDING"},
Target: []string{"ACTIVE", "AVAILABLE"},
Refresh: statusExample(ctx, conn, id),
Timeout: timeout,
}
outputRaw, err := stateConf.WaitForStateContext(ctx)
if output, ok := outputRaw.(*example.Example); ok {
return output, err
}
return nil, err
}
func statusExample(ctx context.Context, conn *example.Client, id string) retry.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := findExampleByID(ctx, conn, id)
if tfresource.NotFound(err) {
return nil, "", nil
}
if err != nil {
return nil, "", err
}
return output, string(output.Status), nil
}
}
func TestAccExampleResource_basic(t *testing.T) {
ctx := acctest.Context(t)
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "provider_example.test"
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckExampleDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccExampleConfig_basic(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckExampleExists(ctx, resourceName),
resource.TestCheckResourceAttr(resourceName, "name", rName),
resource.TestCheckResourceAttrSet(resourceName, "arn"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccExampleResource_disappears(t *testing.T) {
ctx := acctest.Context(t)
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "provider_example.test"
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckExampleDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccExampleConfig_basic(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckExampleExists(ctx, resourceName),
acctest.CheckResourceDisappears(ctx, acctest.Provider, ResourceExample(), resourceName),
),
ExpectNonEmptyPlan: true,
},
},
})
}
func testAccCheckExampleExists(ctx context.Context, name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}
conn := acctest.Provider.Meta().(*conns.Client).ExampleClient(ctx)
_, err := findExampleByID(ctx, conn, rs.Primary.ID)
return err
}
}
func testAccCheckExampleDestroy(ctx context.Context) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.Client).ExampleClient(ctx)
for _, rs := range s.RootModule().Resources {
if rs.Type != "provider_example" {
continue
}
_, err := findExampleByID(ctx, conn, rs.Primary.ID)
if tfresource.NotFound(err) {
continue
}
if err != nil {
return err
}
return fmt.Errorf("Example %s still exists", rs.Primary.ID)
}
return nil
}
}
# Compile tests
go test -c -o /dev/null ./internal/service/<service>
# Run acceptance tests
TF_ACC=1 go test ./internal/service/<service> -run TestAccExample -v -timeout 60m
# Run with specific provider version
TF_ACC=1 go test ./internal/service/<service> -run TestAccExample -v
# Run sweeper to clean up
TF_ACC=1 go test ./internal/service/<service> -sweep=<region> -v
// Handle specific API errors
var notFound *types.ResourceNotFoundException
if errors.As(err, ¬Found) {
// Resource doesn't exist
}
var conflict *types.ConflictException
if errors.As(err, &conflict) {
// Resource state conflict
}
var throttle *types.ThrottlingException
if errors.As(err, &throttle) {
// Rate limited - SDK handles retry
}
// Add error
resp.Diagnostics.AddError(
"Error creating resource",
fmt.Sprintf("Could not create resource: %s", err),
)
// Add warning
resp.Diagnostics.AddWarning(
"Resource modified outside Terraform",
"Resource was modified outside of Terraform, state may be inconsistent",
)
// Add attribute error
resp.Diagnostics.AddAttributeError(
path.Root("name"),
"Invalid name",
"Name must be lowercase alphanumeric",
)
---
subcategory: "Service Name"
layout: "provider"
page_title: "Provider: provider_example"
description: |-
Manages an Example resource.
---
# Resource: provider_example
Manages an Example resource.
## Example Usage
### Basic Usage
\```hcl
resource "provider_example" "example" {
name = "my-example"
}
\```
## Argument Reference
* `name` - (Required) Name of the example.
* `description` - (Optional) Description of the example.
## Attribute Reference
* `id` - ID of the example.
* `arn` - ARN of the example.
## Import
Example can be imported using the ID:
\```
$ terraform import provider_example.example example-id-12345
\```
Weekly Installs
689
Repository
GitHub Stars
481
First Seen
Jan 26, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
github-copilot571
opencode558
codex549
gemini-cli543
amp483
kimi-cli482
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
103,800 周安装
list | schema.ListAttribute | Ordered collections |
set | schema.SetAttribute | Unordered unique items |
map | schema.MapAttribute | Key-value pairs |
object | schema.SingleNestedAttribute | Complex nested config |