Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/4256.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/tencentcloud_teo_l7_acc_rule_v2: add nil checks for response fields and improve error handling
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-06-26
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## Context

The `tencentcloud_teo_l7_acc_rule_v2` resource manages TEO L7 acceleration rules through the cloud API. The resource currently supports `zone_id`, `rule_id`, `status`, `rule_name`, `description`, `branches`, and `rule_priority` parameters. The CRUD operations (Create, Read, Update, Delete) are already implemented using `CreateL7AccRules`, `DescribeL7AccRules`, `ModifyL7AccRule`, and `DeleteL7AccRules` API interfaces from the `teo/v20220901` SDK package.

The core data structure `RuleEngineItem` in the SDK contains: `Status`, `RuleId`, `RuleName`, `Description`, `Branches`, and `RulePriority`.

The current resource uses a composite ID (`zoneId + FILED_SP + ruleId`) and supports import via `ImportStatePassthrough`.

## Goals / Non-Goals

**Goals:**
- Ensure all CRUD API parameters are correctly mapped in the `tencentcloud_teo_l7_acc_rule_v2` resource
- Verify parameter consistency across CreateL7AccRules, ModifyL7AccRule, DeleteL7AccRules, and DescribeL7AccRules interfaces
- Maintain backward compatibility with existing Terraform configurations and state

**Non-Goals:**
- Adding new action types to the `branches.actions` schema (e.g., new operation names)
- Modifying the `RuleEngineItem` data structure or adding new SDK fields
- Changing the composite ID format or import behavior

## Decisions

1. **Parameter mapping approach**: All parameters listed in the requirement (`ZoneId`, `Rules`, `zone_id`, `rule_id`, `status`, `rule_name`, `description`, `branches`, `RuleIds`, `Values`) already exist in the current resource implementation. The Create function maps `zone_id` → `request.ZoneId` and individual fields → `RuleEngineItem` within `request.Rules`. The Modify function maps `zone_id` → `request.ZoneId` and fields → `request.Rule`. The Delete function maps `zone_id` → `request.ZoneId` and `rule_id` → `request.RuleIds`. The Describe (read) uses `Filters` with `Name: "rule-id"` and `Values: [ruleId]`.

2. **DescribeL7AccRules parameter mapping**: The requirement specifies `request.Values` → `rule_id`. In the SDK, `DescribeL7AccRulesRequest` uses `Filters []*Filter` where each `Filter` has `Name` and `Values` fields. The current implementation correctly uses `Filters` with `Name: "rule-id"` and `Values: []string{ruleId}`. This is the correct mapping since the SDK doesn't have a direct `Values` field at the request level.

3. **Backward compatibility**: All parameter additions are Optional or Computed, ensuring existing configurations remain valid.

## Risks / Trade-offs

- [Risk] Parameter naming inconsistency between Create (`ZoneId` → `ZoneId` in requirement vs `zone_id` in schema) → Mitigation: The schema uses snake_case as per Terraform convention; the mapping is correctly handled in the Create/Update functions
- [Risk] The DescribeL7AccRules API uses `Filters` not direct `Values` → Mitigation: Current implementation correctly uses `Filters` with `Name: "rule-id"` which maps to the `rule_id` parameter
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## Why

The `tencentcloud_teo_l7_acc_rule_v2` resource needs to add new parameters to support the full CRUD lifecycle of L7 acceleration rules via the cloud API. The current resource already supports `zone_id`, `rule_id`, `status`, `rule_name`, `description`, `branches`, and `rule_priority`, but needs to be updated to properly map all parameters across the Create, Modify, Delete, and Describe API interfaces.

## What Changes

- Add parameter mappings for the `CreateL7AccRules` API interface (`ZoneId`, `Rules`)
- Add parameter mappings for the `ModifyL7AccRule` API interface (`zone_id`, `rule_id`, `status`, `rule_name`, `description`, `branches`)
- Add parameter mappings for the `DeleteL7AccRules` API interface (`zone_id`, `rule_id`)
- Add parameter mappings for the `DescribeL7AccRules` API interface (`rule_id` via `Values` filter)

## Capabilities

### New Capabilities
- `teo-l7-acc-rule-v2-crud-params`: Full CRUD parameter mapping support for the tencentcloud_teo_l7_acc_rule_v2 resource, ensuring all parameters are correctly mapped across CreateL7AccRules, ModifyL7AccRule, DeleteL7AccRules, and DescribeL7AccRules API interfaces.

### Modified Capabilities
- `rule-ids-output`: Update the existing spec to reflect the new CRUD parameter mappings and ensure consistency with the full API parameter set.

## Impact

- Affected files: `tencentcloud/services/teo/resource_tc_teo_l7_acc_rule_v2.go`, `tencentcloud/services/teo/resource_tc_teo_l7_acc_rule_v2_test.go`, `tencentcloud/services/teo/resource_tc_teo_l7_acc_rule_v2.md`
- Cloud APIs: `CreateL7AccRules`, `ModifyL7AccRule`, `DeleteL7AccRules`, `DescribeL7AccRules` (package: `teo/v20220901`)
- SDK struct: `RuleEngineItem` is the core data structure for L7 Acc Rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## MODIFIED Requirements

### Requirement: No rule_ids computed attribute
The `tencentcloud_teo_l7_acc_rule_v2` resource SHALL NOT have a `rule_ids` computed attribute. The `rule_id` attribute provides the single rule ID managed by this resource.

#### Scenario: rule_ids is not in schema
- **WHEN** a user inspects the `tencentcloud_teo_l7_acc_rule_v2` resource schema
- **THEN** there SHALL NOT be a `rule_ids` attribute
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
## ADDED Requirements

### Requirement: CreateL7AccRules parameter mapping
The `tencentcloud_teo_l7_acc_rule_v2` resource's Create function SHALL map the `zone_id` schema parameter to `request.ZoneId` and the rule fields (`status`, `rule_name`, `description`, `branches`) to a `RuleEngineItem` within `request.Rules` when calling the `CreateL7AccRules` API.

#### Scenario: Create maps zone_id to request.ZoneId
- **WHEN** a user creates a `tencentcloud_teo_l7_acc_rule_v2` resource with `zone_id = "zone-abc123"`
- **THEN** the `CreateL7AccRules` API SHALL be called with `request.ZoneId = "zone-abc123"`

#### Scenario: Create maps rule fields to request.Rules
- **WHEN** a user creates a resource with `status = "enable"`, `rule_name = "test"`, `description = ["desc"]`, `branches = [...]`
- **THEN** the `CreateL7AccRules` API SHALL be called with `request.Rules` containing a `RuleEngineItem` with the corresponding `Status`, `RuleName`, `Description`, and `Branches` fields

### Requirement: ModifyL7AccRule parameter mapping
The `tencentcloud_teo_l7_acc_rule_v2` resource's Update function SHALL map the `zone_id` schema parameter to `request.ZoneId` and the rule fields to `request.Rule` (a `RuleEngineItem`) when calling the `ModifyL7AccRule` API.

#### Scenario: Update maps zone_id to request.ZoneId
- **WHEN** a user updates a `tencentcloud_teo_l7_acc_rule_v2` resource
- **THEN** the `ModifyL7AccRule` API SHALL be called with `request.ZoneId` set from the composite ID's zone_id part

#### Scenario: Update maps rule_id to request.Rule.RuleId
- **WHEN** a user updates a resource with composite ID `zone-abc#rule-xyz`
- **THEN** the `ModifyL7AccRule` API SHALL be called with `request.Rule.RuleId = "rule-xyz"`

#### Scenario: Update maps mutable fields to request.Rule
- **WHEN** a user changes `status`, `rule_name`, `description`, or `branches`
- **THEN** the `ModifyL7AccRule` API SHALL be called with `request.Rule` containing the updated `Status`, `RuleName`, `Description`, and/or `Branches` fields

### Requirement: DeleteL7AccRules parameter mapping
The `tencentcloud_teo_l7_acc_rule_v2` resource's Delete function SHALL map the `zone_id` to `request.ZoneId` and `rule_id` to `request.RuleIds` when calling the `DeleteL7AccRules` API.

#### Scenario: Delete maps zone_id to request.ZoneId
- **WHEN** a user deletes a `tencentcloud_teo_l7_acc_rule_v2` resource with composite ID `zone-abc#rule-xyz`
- **THEN** the `DeleteL7AccRules` API SHALL be called with `request.ZoneId = "zone-abc"`

#### Scenario: Delete maps rule_id to request.RuleIds
- **WHEN** a user deletes a resource with composite ID `zone-abc#rule-xyz`
- **THEN** the `DeleteL7AccRules` API SHALL be called with `request.RuleIds = ["rule-xyz"]`

### Requirement: DescribeL7AccRules parameter mapping
The `tencentcloud_teo_l7_acc_rule_v2` resource's Read function SHALL use `Filters` with `Name: "rule-id"` and `Values: [ruleId]` derived from the `rule_id` parameter when calling the `DescribeL7AccRules` API.

#### Scenario: Read uses Filters with rule-id
- **WHEN** a user reads a `tencentcloud_teo_l7_acc_rule_v2` resource with composite ID `zone-abc#rule-xyz`
- **THEN** the `DescribeL7AccRules` API SHALL be called with `request.ZoneId = "zone-abc"` and `request.Filters` containing `{Name: "rule-id", Values: ["rule-xyz"]}`
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## 1. Schema and CRUD Implementation

- [x] 1.1 Verify and update the `zone_id` parameter mapping in `resource_tc_teo_l7_acc_rule_v2.go` Create function to ensure `request.ZoneId` is correctly set from schema `zone_id`
- [x] 1.2 Verify and update the `Rules` parameter mapping in Create function to ensure rule fields (`status`, `rule_name`, `description`, `branches`) are correctly mapped to `RuleEngineItem` within `request.Rules`
- [x] 1.3 Verify and update the Modify function to ensure `request.ZoneId` is set from `zone_id`, `request.Rule.RuleId` from `rule_id`, and other fields (`status`, `rule_name`, `description`, `branches`) are mapped to `request.Rule`
- [x] 1.4 Verify and update the Delete function to ensure `request.ZoneId` is set from `zone_id` and `request.RuleIds` from `rule_id`
- [x] 1.5 Verify and update the Read function (service layer `DescribeTeoL7AccRuleById`) to ensure `request.Filters` uses `Name: "rule-id"` and `Values: [ruleId]` for querying by `rule_id`

## 2. Testing

- [x] 2.1 Add unit tests in `resource_tc_teo_l7_acc_rule_v2_test.go` using gomonkey mock to verify Create function parameter mapping (zone_id → request.ZoneId, rule fields → request.Rules)
- [x] 2.2 Add unit tests to verify Modify function parameter mapping (zone_id → request.ZoneId, rule_id → request.Rule.RuleId, other fields → request.Rule)
- [x] 2.3 Add unit tests to verify Delete function parameter mapping (zone_id → request.ZoneId, rule_id → request.RuleIds)
- [x] 2.4 Add unit tests to verify Read function uses correct Filters (Name: "rule-id", Values: [ruleId])
- [x] 2.5 Run unit tests with `go test -gcflags="all=-l"` to verify all tests pass

## 3. Documentation

- [x] 3.1 Update `resource_tc_teo_l7_acc_rule_v2.md` to reflect the CRUD parameter mappings and ensure documentation is consistent with the implementation
45 changes: 45 additions & 0 deletions openspec/specs/teo-l7-acc-rule-v2-crud-params/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
## Requirements

### Requirement: CreateL7AccRules parameter mapping
The `tencentcloud_teo_l7_acc_rule_v2` resource's Create function SHALL map the `zone_id` schema parameter to `request.ZoneId` and the rule fields (`status`, `rule_name`, `description`, `branches`) to a `RuleEngineItem` within `request.Rules` when calling the `CreateL7AccRules` API.

#### Scenario: Create maps zone_id to request.ZoneId
- **WHEN** a user creates a `tencentcloud_teo_l7_acc_rule_v2` resource with `zone_id = "zone-abc123"`
- **THEN** the `CreateL7AccRules` API SHALL be called with `request.ZoneId = "zone-abc123"`

#### Scenario: Create maps rule fields to request.Rules
- **WHEN** a user creates a resource with `status = "enable"`, `rule_name = "test"`, `description = ["desc"]`, `branches = [...]`
- **THEN** the `CreateL7AccRules` API SHALL be called with `request.Rules` containing a `RuleEngineItem` with the corresponding `Status`, `RuleName`, `Description`, and `Branches` fields

### Requirement: ModifyL7AccRule parameter mapping
The `tencentcloud_teo_l7_acc_rule_v2` resource's Update function SHALL map the `zone_id` schema parameter to `request.ZoneId` and the rule fields to `request.Rule` (a `RuleEngineItem`) when calling the `ModifyL7AccRule` API.

#### Scenario: Update maps zone_id to request.ZoneId
- **WHEN** a user updates a `tencentcloud_teo_l7_acc_rule_v2` resource
- **THEN** the `ModifyL7AccRule` API SHALL be called with `request.ZoneId` set from the compositeID's zone_id part

#### Scenario: Update maps rule_id to request.Rule.RuleId
- **WHEN** a user updates a resource with composite ID `zone-abc#rule-xyz`
- **THEN** the `ModifyL7AccRule` API SHALL be called with `request.Rule.RuleId = "rule-xyz"`

#### Scenario: Update maps mutable fields to request.Rule
- **WHEN** a user changes `status`, `rule_name`, `description`, or `branches`
- **THEN** the `ModifyL7AccRule` API SHALL be called with `request.Rule` containing the updated `Status`, `RuleName`, `Description`, and/or `Branches` fields

### Requirement: DeleteL7AccRules parameter mapping
The `tencentcloud_teo_l7_acc_rule_v2` resource's Delete function SHALL map the `zone_id` to `request.ZoneId` and `rule_id` to `request.RuleIds` when calling the `DeleteL7AccRules` API.

#### Scenario: Delete maps zone_id to request.ZoneId
- **WHEN** a user deletes a `tencentcloud_teo_l7_acc_rule_v2` resource with composite ID `zone-abc#rule-xyz`
- **THEN** the `DeleteL7AccRules` API SHALL be called with `request.ZoneId = "zone-abc"`

#### Scenario: Delete maps rule_id to request.RuleIds
- **WHEN** a user deletes a resource with composite ID `zone-abc#rule-xyz`
- **THEN** the `DeleteL7AccRules` API SHALL be called with `request.RuleIds = ["rule-xyz"]`

### Requirement: DescribeL7AccRules parameter mapping
The `tencentcloud_teo_l7_acc_rule_v2` resource's Read function SHALL use `Filters` with `Name: "rule-id"` and `Values: [ruleId]` derived from the `rule_id` parameter when calling the `DescribeL7AccRules` API.

#### Scenario: Read uses Filters with rule-id
- **WHEN** a user reads a `tencentcloud_teo_l7_acc_rule_v2` resource with composite ID `zone-abc#rule-xyz`
- **THEN** the `DescribeL7AccRules` API SHALL be called with `request.ZoneId = "zone-abc"` and `request.Filters` containing `{Name: "rule-id", Values: ["rule-xyz"]}`
30 changes: 22 additions & 8 deletions tencentcloud/services/teo/resource_tc_teo_l7_acc_rule_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,13 @@ func ResourceTencentCloudTeoL7AccRuleV2Create(d *schema.ResourceData, meta inter
} else {
log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString())
}
if result.Response != nil && len(result.Response.RuleIds) > 0 && result.Response.RuleIds[0] != nil {
ruleId = *result.Response.RuleIds[0]
if result.Response == nil {
return resource.NonRetryableError(fmt.Errorf("teo_l7_acc_rule_v2 create failed, Response is nil, logId=%s, d.Id()=%s", logId, d.Id()))
}
if len(result.Response.RuleIds) == 0 || result.Response.RuleIds[0] == nil || *result.Response.RuleIds[0] == "" {
return resource.NonRetryableError(fmt.Errorf("teo_l7_acc_rule_v2 create failed, RuleIds is empty, logId=%s, d.Id()=%s", logId, d.Id()))
}
ruleId = *result.Response.RuleIds[0]
return nil
})
if err != nil {
Expand Down Expand Up @@ -149,17 +153,27 @@ func ResourceTencentCloudTeoL7AccRuleV2Read(d *schema.ResourceData, meta interfa
}

if respData == nil || len(respData.Rules) == 0 {
log.Printf("[CRUD] teo_l7_acc_rule_v2 id=%s", d.Id())
d.SetId("")
log.Printf("[WARN]%s resource `teo_l7_acc_rule` [%s] not found, please check if it has been deleted.\n", logId, d.Id())
return nil
}
if len(respData.Rules) > 0 {
rule := respData.Rules[0]
_ = d.Set("status", rule.Status)
_ = d.Set("rule_name", rule.RuleName)
_ = d.Set("description", rule.Description)
_ = d.Set("rule_priority", rule.RulePriority)
_ = d.Set("branches", resourceTencentCloudTeoL7AccRuleSetBranchs(rule.Branches))
if rule.Status != nil {
_ = d.Set("status", rule.Status)
}
if rule.RuleName != nil {
_ = d.Set("rule_name", rule.RuleName)
}
if rule.Description != nil {
_ = d.Set("description", rule.Description)
}
if rule.RulePriority != nil {
_ = d.Set("rule_priority", rule.RulePriority)
}
if rule.Branches != nil {
_ = d.Set("branches", resourceTencentCloudTeoL7AccRuleSetBranchs(rule.Branches))
}
}

return nil
Expand Down
Loading
Loading