Skip to content

Commit 8c01e29

Browse files
author
greyworld
committed
feat(eg): add new operation resource for event subscription
1 parent 8974fe6 commit 8c01e29

File tree

5 files changed

+317
-8
lines changed

5 files changed

+317
-8
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
subcategory: "EventGrid (EG)"
3+
layout: "huaweicloud"
4+
page_title: "Huaweicloud: huaweicloud_eg_event_subscription_action"
5+
description: |-
6+
Manages an EG event subscription action resource within HuaweiCloud.
7+
---
8+
9+
# huaweicloud_eg_event_subscription_action
10+
11+
Manages an EG event subscription action resource within HuaweiCloud.
12+
13+
## Example Usage
14+
15+
### Enable event subscription
16+
17+
```hcl
18+
variable "subscription_ids" {
19+
type = list(string)
20+
}
21+
22+
resource "huaweicloud_eg_event_subscription_action" "enable" {
23+
subscription_ids = var.subscription_ids
24+
operation = "ENABLE"
25+
}
26+
```
27+
28+
### Disable event subscription
29+
30+
```hcl
31+
variable "subscription_ids" {
32+
type = list(string)
33+
}
34+
35+
resource "huaweicloud_eg_event_subscription_action" "disable" {
36+
subscription_ids = var.subscription_ids
37+
operation = "DISABLE"
38+
}
39+
```
40+
41+
## Argument Reference
42+
43+
The following arguments are supported:
44+
45+
* `region` - (Optional, String, ForceNew) The region where the event subscription actions are located.
46+
If omitted, the provider-level region will be used.
47+
Changing this creates a new resource.
48+
49+
* `subscription_ids` - (Required, List, ForceNew) Specifies the list of subscription IDs to be operated.
50+
Changing this creates a new resource.
51+
52+
* `operation` - (Required, Bool, ForceNew) Specifies whether to enable the event subscription.
53+
Changing this creates a new resource.
54+
The valid values are as follows:
55+
+ **ENABLE**
56+
+ **DISABLE**
57+
58+
* `enterprise_project_id` - (Optional, String) Specifies the ID of the enterprise project to which the event subscription action belongs.
59+
60+
## Attribute Reference
61+
62+
In addition to all arguments above, the following attributes are exported:
63+
64+
* `id` - The resource ID.
65+
66+
## Timeouts
67+
68+
This resource provides the following timeouts configuration options:
69+
70+
* `create` - Default is 3 minutes.

huaweicloud/provider.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2288,12 +2288,13 @@ func Provider() *schema.Provider {
22882288
"huaweicloud_dws_workload_queue_user_associate": dws.ResourceWorkloadQueueUserAssociate(),
22892289
"huaweicloud_dws_workload_queue": dws.ResourceWorkLoadQueue(),
22902290

2291-
"huaweicloud_eg_connection": eg.ResourceConnection(),
2292-
"huaweicloud_eg_custom_event_channel": eg.ResourceCustomEventChannel(),
2293-
"huaweicloud_eg_custom_event_source": eg.ResourceCustomEventSource(),
2294-
"huaweicloud_eg_endpoint": eg.ResourceEndpoint(),
2295-
"huaweicloud_eg_event_stream": eg.ResourceEventStream(),
2296-
"huaweicloud_eg_event_subscription": eg.ResourceEventSubscription(),
2291+
"huaweicloud_eg_connection": eg.ResourceConnection(),
2292+
"huaweicloud_eg_custom_event_channel": eg.ResourceCustomEventChannel(),
2293+
"huaweicloud_eg_custom_event_source": eg.ResourceCustomEventSource(),
2294+
"huaweicloud_eg_endpoint": eg.ResourceEndpoint(),
2295+
"huaweicloud_eg_event_stream": eg.ResourceEventStream(),
2296+
"huaweicloud_eg_event_subscription": eg.ResourceEventSubscription(),
2297+
"huaweicloud_eg_event_subscription_action": eg.ResourceEventSubscriptionAction(),
22972298

22982299
"huaweicloud_elb_certificate": elb.ResourceCertificateV3(),
22992300
"huaweicloud_elb_certificate_private_key_echo": elb.ResourceCertificatePrivateKeyEcho(),

huaweicloud/services/acceptance/acceptance.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,12 +501,13 @@ var (
501501
HW_CODEARTS_SSH_CREDENTIAL_ID = os.Getenv("HW_CODEARTS_SSH_CREDENTIAL_ID")
502502

503503
HW_EG_TEST_ON = os.Getenv("HW_EG_TEST_ON") // Whether to run the EG related tests.
504-
HW_EG_CHANNEL_ID = os.Getenv("HW_EG_CHANNEL_ID")
505504
HW_EG_AGENCY_NAME = os.Getenv("HW_EG_AGENCY_NAME")
505+
HW_EG_CHANNEL_ID = os.Getenv("HW_EG_CHANNEL_ID")
506506
// Currently, only up to 3 target connections are allowed to be created, so this variable is provided.
507507
// The IDs of the EG connections. Using commas (,) to separate multiple IDs, the first ID is the webhook connection,
508508
// the second is the Kafka connection, and the connections cannot be the default.
509-
HW_EG_CONNECTION_IDS = os.Getenv("HW_EG_CONNECTION_IDS")
509+
HW_EG_CONNECTION_IDS = os.Getenv("HW_EG_CONNECTION_IDS")
510+
HW_EG_EVENT_SUBSCRIPTION_ID = os.Getenv("HW_EG_EVENT_SUBSCRIPTION_ID")
510511

511512
HW_KOOGALLERY_ASSET = os.Getenv("HW_KOOGALLERY_ASSET")
512513

@@ -2591,6 +2592,13 @@ func TestAccPreCheckEgConnectionIds(t *testing.T) {
25912592
}
25922593
}
25932594

2595+
// lintignore:AT003
2596+
func TestAccPreCheckEgEventSubscriptionId(t *testing.T) {
2597+
if HW_EG_EVENT_SUBSCRIPTION_ID == "" {
2598+
t.Skip("The sub-resource acceptance test of the EG event subscription must set 'HW_EG_EVENT_SUBSCRIPTION_ID'")
2599+
}
2600+
}
2601+
25942602
// lintignore:AT003
25952603
func TestAccPreCheckLtsAomAccess(t *testing.T) {
25962604
if HW_LTS_CLUSTER_ID == "" || HW_LTS_CLUSTER_NAME == "" {
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package eg
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
8+
9+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance"
10+
)
11+
12+
func TestAccEventSubscriptionAction_basic(t *testing.T) {
13+
var (
14+
rcName = "huaweicloud_eg_event_subscription_action.test"
15+
)
16+
17+
resource.ParallelTest(t, resource.TestCase{
18+
PreCheck: func() {
19+
acceptance.TestAccPreCheck(t)
20+
acceptance.TestAccPreCheckEgEventSubscriptionId(t)
21+
},
22+
ProviderFactories: acceptance.TestAccProviderFactories,
23+
// This resource is a one-time action resource and there is no logic in the delete method.
24+
// lintignore:AT001
25+
CheckDestroy: nil,
26+
Steps: []resource.TestStep{
27+
{
28+
Config: testEventSubscriptionAction_basic(),
29+
Check: resource.ComposeTestCheckFunc(
30+
resource.TestCheckResourceAttr(rcName, "operation", "ENABLE"),
31+
resource.TestCheckResourceAttr(rcName, "subscription_ids.#", "1"),
32+
),
33+
},
34+
{
35+
Config: testEventSubscriptionAction_disable(),
36+
Check: resource.ComposeTestCheckFunc(
37+
resource.TestCheckResourceAttr(rcName, "operation", "DISABLE"),
38+
resource.TestCheckResourceAttr(rcName, "subscription_ids.#", "1"),
39+
),
40+
},
41+
},
42+
})
43+
}
44+
45+
func testEventSubscriptionAction_basic() string {
46+
return fmt.Sprintf(`
47+
resource "huaweicloud_eg_event_subscription_action" "test" {
48+
subscription_ids = ["%[1]s"]
49+
operation = "ENABLE"
50+
}
51+
`, acceptance.HW_EG_EVENT_SUBSCRIPTION_ID)
52+
}
53+
54+
func testEventSubscriptionAction_disable() string {
55+
return fmt.Sprintf(`
56+
resource "huaweicloud_eg_event_subscription_action" "test" {
57+
subscription_ids = ["%[1]s"]
58+
operation = "DISABLE"
59+
}
60+
`, acceptance.HW_EG_EVENT_SUBSCRIPTION_ID)
61+
}
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package eg
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
"time"
8+
9+
"github.com/hashicorp/go-uuid"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
13+
14+
"github.com/chnsz/golangsdk"
15+
16+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config"
17+
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils"
18+
)
19+
20+
var eventSubscriptionNonUpdateParams = []string{"subscription_ids", "operation", "enterprise_project_id"}
21+
22+
// @API EG POST /v1/{project_id}/subscriptions/operation
23+
func ResourceEventSubscriptionAction() *schema.Resource {
24+
return &schema.Resource{
25+
CreateContext: resourceEventSubscriptionActionCreate,
26+
ReadContext: resourceEventSubscriptionActionRead,
27+
UpdateContext: resourceEventSubscriptionActionUpdate,
28+
DeleteContext: resourceEventSubscriptionActionDelete,
29+
30+
Timeouts: &schema.ResourceTimeout{
31+
Create: schema.DefaultTimeout(3 * time.Minute),
32+
},
33+
34+
CustomizeDiff: config.FlexibleForceNew(eventSubscriptionNonUpdateParams),
35+
36+
Schema: map[string]*schema.Schema{
37+
"region": {
38+
Type: schema.TypeString,
39+
Optional: true,
40+
Computed: true,
41+
ForceNew: true,
42+
Description: `The region where the event subscriptions are located.`,
43+
},
44+
"subscription_ids": {
45+
Type: schema.TypeList,
46+
Required: true,
47+
ForceNew: true,
48+
Elem: &schema.Schema{Type: schema.TypeString},
49+
Description: `The list of subscription IDs to be operated.`,
50+
},
51+
"operation": {
52+
Type: schema.TypeString,
53+
Required: true,
54+
Description: `Whether to enable the event subscription.`,
55+
},
56+
"enterprise_project_id": {
57+
Type: schema.TypeString,
58+
Optional: true,
59+
Description: `The ID of the enterprise project.`,
60+
},
61+
// Internal parameters.
62+
"enable_force_new": {
63+
Type: schema.TypeString,
64+
Optional: true,
65+
ValidateFunc: validation.StringInSlice([]string{"true", "false"}, false),
66+
Description: utils.SchemaDesc("", utils.SchemaDescInput{Internal: true}),
67+
},
68+
},
69+
}
70+
}
71+
72+
func buildEventSubscriptionActionBodyParams(d *schema.ResourceData) map[string]interface{} {
73+
return map[string]interface{}{
74+
"subscription_ids": d.Get("subscription_ids"),
75+
"operation": d.Get("operation"),
76+
}
77+
}
78+
79+
func buildEventSubscriptionActionQueryParams(d *schema.ResourceData) string {
80+
res := ""
81+
if v, ok := d.GetOk("enterprise_project_id"); ok {
82+
res += fmt.Sprintf("?enterprise_project_id=%s", v.(string))
83+
}
84+
return res
85+
}
86+
87+
func checkEventSubscriptionActionResult(respBody interface{}) error {
88+
failedCount := utils.PathSearch("failed_count", respBody, 0).(int)
89+
if failedCount > 0 {
90+
events := utils.PathSearch("events", respBody, make([]interface{}, 0)).([]interface{})
91+
var failedSubscriptions []string
92+
for _, event := range events {
93+
if errorCode := utils.PathSearch("error_code", event, nil); errorCode != nil {
94+
subscriptionId := utils.PathSearch("subscription_id", event, "").(string)
95+
errorMsg := utils.PathSearch("error_msg", event, "").(string)
96+
failedSubscriptions = append(failedSubscriptions, fmt.Sprintf("subscription %s: %s (%s)", subscriptionId, errorMsg, errorCode))
97+
}
98+
}
99+
return fmt.Errorf("failed to operate %d subscription(s): %s", failedCount, strings.Join(failedSubscriptions, "; "))
100+
}
101+
return nil
102+
}
103+
104+
func resourceEventSubscriptionActionCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
105+
var (
106+
cfg = meta.(*config.Config)
107+
region = cfg.GetRegion(d)
108+
httpUrl = "v1/{project_id}/subscriptions/operation"
109+
)
110+
111+
client, err := cfg.NewServiceClient("eg", region)
112+
if err != nil {
113+
return diag.Errorf("error creating EG client: %s", err)
114+
}
115+
116+
createPath := client.Endpoint + httpUrl
117+
createPath = strings.ReplaceAll(createPath, "{project_id}", client.ProjectID)
118+
createPath += buildEventSubscriptionActionQueryParams(d)
119+
createOpt := golangsdk.RequestOpts{
120+
KeepResponseBody: true,
121+
MoreHeaders: map[string]string{
122+
"Content-Type": "application/json",
123+
},
124+
JSONBody: buildEventSubscriptionActionBodyParams(d),
125+
}
126+
127+
resp, err := client.Request("POST", createPath, &createOpt)
128+
if err != nil {
129+
return diag.Errorf("error creating EG event subscription action: %s", err)
130+
}
131+
132+
respBody, err := utils.FlattenResponse(resp)
133+
if err != nil {
134+
return diag.FromErr(err)
135+
}
136+
137+
// Check if there are any failed operations
138+
err = checkEventSubscriptionActionResult(respBody)
139+
if err != nil {
140+
return diag.FromErr(err)
141+
}
142+
143+
randomUUID, err := uuid.GenerateUUID()
144+
if err != nil {
145+
return diag.Errorf("unable to generate ID: %s", err)
146+
}
147+
d.SetId(randomUUID)
148+
149+
return resourceEventSubscriptionActionRead(ctx, d, meta)
150+
}
151+
152+
func resourceEventSubscriptionActionRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
153+
return nil
154+
}
155+
156+
func resourceEventSubscriptionActionUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
157+
return nil
158+
}
159+
160+
func resourceEventSubscriptionActionDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
161+
errorMsg := `This resource is a one-time action resource using to operate event subscription status. Deleting this resource will
162+
not clear the corresponding request record, but will only remove the resource information from the tfstate file.`
163+
return diag.Diagnostics{
164+
diag.Diagnostic{
165+
Severity: diag.Warning,
166+
Summary: errorMsg,
167+
},
168+
}
169+
}

0 commit comments

Comments
 (0)