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/4321.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
tencentcloud_teo_plan_for_zone
```
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ require (
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.3.105
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cloudaudit v1.0.1033
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cls v1.3.131
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.132
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.136
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/config v1.3.80
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.3.130
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cwp v1.3.30
Expand Down Expand Up @@ -93,7 +93,7 @@ require (
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tdcpg v1.0.533
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tdmq v1.3.113
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tem v1.0.578
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.3.121
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.3.136
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tke v1.3.107
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/trocket v1.1.0
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tse v1.0.857
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -996,16 +996,16 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.112/go.mod
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.113/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.115/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.118/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.121/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.122/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.123/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.124/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.125/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.127/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.130/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.131/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.132 h1:42RfJnwzMprfKEJrM9fyhHu1jXyg8xvSJ1A1qb9Qun8=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.132/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.136 h1:06MPEiR1oZzRyNux2jshwMh67C0Zp4kRWvRfj46EcYs=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.136/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/config v1.3.80 h1:chnsNBeJn3MieFLki4hpbzoml5NiTvLVzOTqYRVxQho=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/config v1.3.80/go.mod h1:B/ezGtlvDhZlleNM+2QdvZccrUi+J+fN6vMnDDsZnuM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/controlcenter v1.1.51 h1:pGwrfCBBCt1u+EDHwfNj9NLQpvk5MVKVMcsE7SvwqM4=
Expand Down Expand Up @@ -1121,8 +1121,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tdmq v1.3.113 h1:2sulWz
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tdmq v1.3.113/go.mod h1:uCUT6rfNap46k8JHzdPIz3WvYjiQPDkOBZ+b2GrIpUE=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tem v1.0.578 h1:vBpQhUroO+FAslUmsDWGi8nvczsqZBWVgQwlnyT0Aj8=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tem v1.0.578/go.mod h1:UlojGQh/9wb7/uXPNi7PvMral1CNAskVDNgqJEV83l0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.3.121 h1:SdW1CsEOUSABdz3YHXSw7nESExvD4fR43ZfBFYaD2OQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.3.121/go.mod h1:r8LzDVp59qZs+Pe65TiXnGKZSu05QB7cYd6XpK6XZ0s=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.3.136 h1:rgjFH09Z/PH6v7C6uum5pqli+d3AxzSH1gdhqLYiw1s=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.3.136/go.mod h1:hROu6uk1E9l58lfZKQ15BEb9EF/rc3PP8Uxo1M7WdJg=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/thpc v1.0.998 h1:f4/n0dVKQTD06xJ84B5asHViNJHrZmGojdAWEPIsITM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/thpc v1.0.998/go.mod h1:fyi/HUwCwVe2NCCCjz8k/C5GwPu3QazCZO+OBJ3MhLk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tke v1.3.107 h1:Yky7eL8FnkO89MvxERN3tniBQjstZzjIX8I91A4la/k=
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-07-20
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
## Context

TEO (EdgeOne) exposes a `CreatePlanForZone` API in the vendored SDK `teo/v20220901` (verified present — no SDK upgrade needed):

- `CreatePlanForZone(request)` — purchases a plan for a zone that has not yet bound a plan. Request inputs: `ZoneId *string`, `PlanType *string`. Response outputs: `ResourceNames []*string`, `DealNames []*string`, `RequestId *string`.
- The API is synchronous; no async task/polling is needed.

This is a **one-time operation resource** (RESOURCE_KIND_OPERATION), following the style of `tencentcloud_teo_identify_zone_operation`: it has `Create`, `Read`, `Delete` (no `Update`), performs the action on Create, and treats Read/Delete as no-ops. Unlike `tencentcloud_teo_plan` (which uses the separate `CreatePlan` API and is a full CRUD resource), this resource targets a zone that has no bound plan and only performs the purchase action.

## Goals / Non-Goals

**Goals:**
- Trigger plan purchase for a zone via `CreatePlanForZone` on create, with retry and nil-safe response handling.
- Auto-generate the resource ID (per business rule), using `helper.BuildToken()`.
- Surface the response's `ResourceNames` and `DealNames` as computed attributes.
- Ship resource example `.md`, website docs, unit test, and provider registration.

**Non-Goals:**
- No revert/cancel of a purchased plan on delete (the API has no such capability); Delete is a no-op.
- No Read API to query purchase status; Read is a no-op that returns nil.
- No Timeouts block (synchronous call, no async status polling needed).

## Decisions

### Resource name and file layout
- Resource: `tencentcloud_teo_plan_for_zone`
- Files under `tencentcloud/services/teo/`:
- `resource_tc_teo_plan_for_zone_operation.go`
- `resource_tc_teo_plan_for_zone_operation.md`
- `resource_tc_teo_plan_for_zone_operation_test.go`
- Website doc: `website/docs/r/teo_plan_for_zone.html.markdown`
- Constructor `ResourceTencentCloudTeoPlanForZone()`, registered in `provider.go`.

### Schema
- Required (ForceNew):
- `zone_id` (TypeString): Zone ID.
- `plan_type` (TypeString): Plan type to purchase. Valid values: `sta`, `sta_with_bot`, `sta_cm`, `sta_cm_with_bot`, `sta_global`, `sta_global_with_bot`, `ent`, `ent_with_bot`, `ent_cm`, `ent_cm_with_bot`, `ent_global`, `ent_global_with_bot`.
- Computed:
- `resource_names` (TypeList, element TypeString): List of purchased resource names returned by the API.
- `deal_names` (TypeList, element TypeString): List of purchased order/deal names returned by the API.

### CRUD mapping (operation-type, following `tencentcloud_teo_identify_zone_operation`)
- **Create**: build `CreatePlanForZoneRequest` from `zone_id` and `plan_type`; call the service-layer `TeoPlanForZone` helper inside `resource.Retry(tccommon.ReadRetryTimeout, ...)`; on success `d.SetId(helper.BuildToken())`; then nil-safe set computed `resource_names` and `deal_names`; finally call Read.
- **Read**: no-op, return nil (no query API for the purchase result).
- **Delete**: no-op, return nil (state removal only).

### Service-layer method
- Add `TeoPlanForZone(zoneId, planType string) (resourceNames, dealNames []*string, errRet error)` to `service_tencentcloud_teo.go`, following the `TeoIdentifyZone` pattern: build request, ratelimit check, call `me.client.UseTeoV20220901Client().CreatePlanForZone(request)`, nil-safe access to `response.Response`.

### Retry placement
- Per the business rules, the retry wraps only the API call. The `d.SetId()` and `d.Set(...)` calls happen after the retry block (outside it), in the success path after the retry error handling.

## Risks / Trade-offs

- [Plan purchase is irreversible and account/billing-impacting] → Mitigation: document clearly that Delete only removes the resource from state and does not cancel the plan. The `plan_type` is ForceNew, so changing it forces recreation (a new purchase).
- [No Read API to verify the purchase] → Mitigation: Read is a no-op; the computed `resource_names` and `deal_names` are set once at create time from the API response and persisted in state.
- [Re-running create on a zone that already has a plan] → Mitigation: rely on the API's own behavior; `CreatePlanForZone` will surface an error (e.g., `InvalidParameter.ZoneHasBeenBound`) which the retry helper surfaces to the user.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## Why

EdgeOne (TEO) zones that have not yet purchased a plan cannot be fully managed via Terraform. Currently, users must purchase a plan for a zone manually in the console before they can manage the zone's configuration through Terraform. The `CreatePlanForZone` API exists to programmatically purchase a plan for an unbound zone, but there is no Terraform resource exposing this action. Adding a one-time operation resource lets users purchase a plan for a zone entirely from infrastructure-as-code.

## What Changes

- Add a new **operation-type** (one-time action) resource `tencentcloud_teo_plan_for_zone` that purchases a plan for a zone that has no bound plan, via the `CreatePlanForZone` API.
- Create lifecycle calls `CreatePlanForZone` with `ZoneId` and `PlanType` inputs and exposes `ResourceNames` and `DealNames` from the response as computed attributes.
- The resource unique ID is auto-generated (via `helper.BuildToken()`).
- Read, Update, and Delete lifecycles are no-ops (one-time operation; no state to query or revert).
- Provider registration, resource example doc (`.md`), website documentation, and unit test are added.

## Capabilities

### New Capabilities
- `teo-plan-for-zone-operation`: A one-time operation resource that purchases a TEO plan for a zone via the `CreatePlanForZone` API.

### Modified Capabilities
<!-- None: brand-new resource, no existing requirements change. -->

## Impact

- New file: `tencentcloud/services/teo/resource_tc_teo_plan_for_zone_operation.go`
- New file: `tencentcloud/services/teo/resource_tc_teo_plan_for_zone_operation.md`
- New file: `tencentcloud/services/teo/resource_tc_teo_plan_for_zone_operation_test.go`
- New file: `website/docs/r/teo_plan_for_zone.html.markdown` (generated via `make doc`)
- Modified: `tencentcloud/provider.go` (register resource), `tencentcloud/provider.md`, `website/tencentcloud.erb`
- SDK: uses existing `teo/v20220901` API `CreatePlanForZone` (already present in vendored SDK — no SDK changes required). The API is synchronous; no async polling is needed.
- No breaking changes; purely additive.
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
## ADDED Requirements

### Requirement: Purchase a plan for a TEO zone

The resource `tencentcloud_teo_plan_for_zone` SHALL purchase a plan for a zone that has not yet bound a plan via the `CreatePlanForZone` API. As a one-time operation resource, it MUST auto-generate its unique ID. The `CreatePlanForZone` API accepts `ZoneId` and `PlanType` inputs and returns `ResourceNames` and `DealNames`.

#### Scenario: Purchase a plan for a zone

- **WHEN** the user applies the resource with `zone_id` and `plan_type` set
- **THEN** the resource calls `CreatePlanForZone` wrapped in a retry mechanism with the provided `ZoneId` and `PlanType`
- **AND** sets an auto-generated unique resource ID
- **AND** populates the computed `resource_names` and `deal_names` attributes from the response in a nil-safe manner
- **AND** then calls Read

#### Scenario: Plan purchase with empty response

- **WHEN** the `CreatePlanForZone` response is nil or `response.Response` is nil
- **THEN** the resource SHALL return a NonRetryableError to avoid persisting an empty state

### Requirement: Resource schema definition

The system SHALL define the following schema for `tencentcloud_teo_plan_for_zone`:

Required parameters (ForceNew):
- `zone_id` (TypeString): Zone ID
- `plan_type` (TypeString): Plan type to purchase

Computed parameters:
- `resource_names` (TypeList, element TypeString): List of purchased resource names returned by `CreatePlanForZone`
- `deal_names` (TypeList, element TypeString): List of purchased order/deal names returned by `CreatePlanForZone`

#### Scenario: Schema validates required fields

- **WHEN** user omits `zone_id` or `plan_type` in the resource configuration
- **THEN** Terraform SHALL produce a validation error indicating the missing required field

#### Scenario: All input parameters are ForceNew

- **WHEN** user changes `zone_id` or `plan_type` after creation
- **THEN** Terraform SHALL force resource recreation

### Requirement: Empty Read/Update/Delete methods

The system SHALL implement empty Read, Update, and Delete methods for `tencentcloud_teo_plan_for_zone` resource, as this is a RESOURCE_KIND_OPERATION type. There is no query API for the purchase result, so Read is a no-op.

#### Scenario: Read method returns nil

- **WHEN** Terraform calls the Read method
- **THEN** the system SHALL return nil without making any API calls

#### Scenario: Delete method returns nil

- **WHEN** Terraform calls the Delete method
- **THEN** the system SHALL return nil without making any API calls, and the purchased plan is not reverted

### Requirement: Resource registration in provider

The system SHALL register `tencentcloud_teo_plan_for_zone` resource in `tencentcloud/provider.go` with the resource name "tencentcloud_teo_plan_for_zone" and add the corresponding entry in `tencentcloud/provider.md`.

#### Scenario: Resource available in provider

- **WHEN** user references `tencentcloud_teo_plan_for_zone` in Terraform configuration
- **THEN** the provider SHALL recognize and process the resource

### Requirement: Unit tests with gomonkey mock

The system SHALL include unit tests in `resource_tc_teo_plan_for_zone_operation_test.go` using gomonkey to mock the TEO API client calls. Tests SHALL cover the Create operation with a successful response.

#### Scenario: Test successful plan purchase

- **WHEN** unit test runs with mocked `CreatePlanForZone` returning `ResourceNames` and `DealNames`
- **THEN** the test SHALL verify the resource ID is set and computed fields are populated

### Requirement: Resource documentation

The system SHALL include a `resource_tc_teo_plan_for_zone_operation.md` documentation file with a description, and example usage. No Import section is needed for an OPERATION type resource.

#### Scenario: Documentation file exists

- **WHEN** the resource is added
- **THEN** a corresponding .md file SHALL exist in the teo service directory with proper format following the gendoc README guidelines
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## 1. Service Layer

- [x] 1.1 Add `TeoPlanForZone(zoneId, planType string) (resourceNames, dealNames []*string, errRet error)` method to `tencentcloud/services/teo/service_tencentcloud_teo.go`, following the `TeoIdentifyZone` pattern: build `CreatePlanForZoneRequest`, set `ZoneId` and `PlanType`, ratelimit check, call `me.client.UseTeoV20220901Client().CreatePlanForZone(request)`, nil-safe access to `response.Response`

## 2. Resource Implementation

- [x] 2.1 Create `tencentcloud/services/teo/resource_tc_teo_plan_for_zone_operation.go` with constructor `ResourceTencentCloudTeoPlanForZone()`, operation-type code style following `tencentcloud_teo_identify_zone_operation`
- [x] 2.2 Define schema: required ForceNew `zone_id` (TypeString), required ForceNew `plan_type` (TypeString); computed `resource_names` (TypeList, elem TypeString), computed `deal_names` (TypeList, elem TypeString)
- [x] 2.3 Implement Create: build `CreatePlanForZoneRequest` from `zone_id` and `plan_type`, call `TeoPlanForZone` inside `resource.Retry(tccommon.ReadRetryTimeout, ...)`, after retry success set `d.SetId(helper.BuildToken())` and nil-safe set computed `resource_names` and `deal_names`, then call Read
- [x] 2.4 Implement Read: no-op (return nil)
- [x] 2.5 Implement Delete: no-op (return nil)
- [x] 2.6 Ensure nil-safe response access: if response or response.Response is nil, return NonRetryableError; all response-value access is nil-safe

## 3. Provider Registration

- [x] 3.1 Register `tencentcloud_teo_plan_for_zone` in `tencentcloud/provider.go` ResourcesMap
- [x] 3.2 Add the resource entry to `tencentcloud/provider.md`

## 4. Documentation

- [x] 4.1 Create `tencentcloud/services/teo/resource_tc_teo_plan_for_zone_operation.md` example file, format following `resource_tc_teo_identify_zone_operation.md` (description with TEO product name + Example Usage; no Import section for OPERATION type)
- [ ] 4.2 Generate `website/docs/r/teo_plan_for_zone.html.markdown` via `make doc` (do not hand-write) and confirm `website/tencentcloud.erb` link entry

## 5. Unit Test

- [x] 5.1 Create `tencentcloud/services/teo/resource_tc_teo_plan_for_zone_operation_test.go`, using gomonkey to mock the TEO API client, naming/format following `resource_tc_teo_identify_zone_operation_test.go`; cover Create with successful response

## 6. Verification

- [ ] 6.1 Run `gofmt` on changed Go files
- [x] 6.2 Run `go test -gcflags=all=-l ./tencentcloud/services/teo/ -run TestAccTencentCloudTeoPlanForZone` to confirm unit tests pass
- [ ] 6.3 Run `make doc` and verify generated website doc is consistent with the `.md` example
Loading
Loading