Skip to content

Commit d7b666d

Browse files
author
greyworld
committed
feat(eg): add new operation resource for event subscription
1 parent 7766795 commit d7b666d

File tree

5 files changed

+282
-13
lines changed

5 files changed

+282
-13
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
subcategory: "EventGrid (EG)"
3+
layout: "huaweicloud"
4+
page_title: "Huaweicloud: huaweicloud_eg_event_subscription_batch_action"
5+
description: |-
6+
Use this resource to operate the EG event subscription within HuaweiCloud.
7+
---
8+
9+
# huaweicloud_eg_event_subscription_batch_action
10+
11+
Use this resource to operate the EG event subscription within HuaweiCloud.
12+
13+
-> This resource is only a one-time action resource for operating event subscription status. Deleting this resource will
14+
not clear the corresponding request record, but will only remove the resource information from the tfstate file.
15+
16+
## Example Usage
17+
18+
```hcl
19+
variable "subscription_ids" {
20+
type = list(string)
21+
}
22+
23+
resource "huaweicloud_eg_event_subscription_batch_action" "example" {
24+
subscription_ids = var.subscription_ids
25+
operation = "ENABLE"
26+
}
27+
```
28+
29+
## Argument Reference
30+
31+
The following arguments are supported:
32+
33+
* `region` - (Optional, String, ForceNew) Specifies the region where the event subscriptions are located.
34+
If omitted, the provider-level region will be used.
35+
Changing this creates a new resource.
36+
37+
* `subscription_ids` - (Required, List, NonUpdatable) Specifies the list of subscription IDs to be operated.
38+
The single operation only can handle up to `10` event subscriptions at most.
39+
40+
* `operation` - (Required, String, NonUpdatable) Specifies whether to enable the event subscription.
41+
The valid values are as follows:
42+
+ **ENABLE**
43+
+ **DISABLE**
44+
45+
* `enterprise_project_id` - (Optional, String, NonUpdatable) Specifies the ID of the enterprise project to which the
46+
subscriptions belong.
47+
This parameter is only valid for enterprise users.
48+
49+
## Attribute Reference
50+
51+
In addition to all arguments above, the following attributes are exported:
52+
53+
* `id` - The resource ID.

huaweicloud/provider.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2317,13 +2317,14 @@ func Provider() *schema.Provider {
23172317
"huaweicloud_dws_workload_queue_user_associate": dws.ResourceWorkloadQueueUserAssociate(),
23182318
"huaweicloud_dws_workload_queue": dws.ResourceWorkLoadQueue(),
23192319

2320-
"huaweicloud_eg_connection": eg.ResourceConnection(),
2321-
"huaweicloud_eg_custom_event_channel": eg.ResourceCustomEventChannel(),
2322-
"huaweicloud_eg_custom_event_source": eg.ResourceCustomEventSource(),
2323-
"huaweicloud_eg_endpoint": eg.ResourceEndpoint(),
2324-
"huaweicloud_eg_event_batch_action": eg.ResourceEventBatchAction(),
2325-
"huaweicloud_eg_event_stream": eg.ResourceEventStream(),
2326-
"huaweicloud_eg_event_subscription": eg.ResourceEventSubscription(),
2320+
"huaweicloud_eg_connection": eg.ResourceConnection(),
2321+
"huaweicloud_eg_custom_event_channel": eg.ResourceCustomEventChannel(),
2322+
"huaweicloud_eg_custom_event_source": eg.ResourceCustomEventSource(),
2323+
"huaweicloud_eg_endpoint": eg.ResourceEndpoint(),
2324+
"huaweicloud_eg_event_batch_action": eg.ResourceEventBatchAction(),
2325+
"huaweicloud_eg_event_stream": eg.ResourceEventStream(),
2326+
"huaweicloud_eg_event_subscription": eg.ResourceEventSubscription(),
2327+
"huaweicloud_eg_event_subscription_batch_action": eg.ResourceEventSubscriptionBatchAction(),
23272328

23282329
"huaweicloud_elb_certificate": elb.ResourceCertificateV3(),
23292330
"huaweicloud_elb_certificate_private_key_echo": elb.ResourceCertificatePrivateKeyEcho(),

huaweicloud/services/acceptance/acceptance.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -501,13 +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")
510-
HW_EG_EVENT_SOURCE_ID = os.Getenv("HW_EG_EVENT_SOURCE_ID")
509+
HW_EG_CONNECTION_IDS = os.Getenv("HW_EG_CONNECTION_IDS")
510+
HW_EG_EVENT_SUBSCRIPTION_IDS = os.Getenv("HW_EG_EVENT_SUBSCRIPTION_IDS")
511511

512512
HW_KOOGALLERY_ASSET = os.Getenv("HW_KOOGALLERY_ASSET")
513513

@@ -2584,9 +2584,10 @@ func TestAccPreCheckEgConnectionIds(t *testing.T) {
25842584
}
25852585

25862586
// lintignore:AT003
2587-
func TestAccPreCheckEgEventSourceId(t *testing.T) {
2588-
if HW_EG_EVENT_SOURCE_ID == "" {
2589-
t.Skip("The sub-resource acceptance test of the EG event source must set 'HW_EG_EVENT_SOURCE_ID'")
2587+
func TestAccPreCheckEgEventSubscriptionIds(t *testing.T, min int) {
2588+
if HW_EG_EVENT_SUBSCRIPTION_IDS == "" || len(strings.Split(HW_EG_EVENT_SUBSCRIPTION_IDS, ",")) > min {
2589+
t.Skipf(`At least %d subscription ID(s) must be supported during the HW_EG_EVENT_SUBSCRIPTION_IDS, separated by
2590+
commas (,).`, min)
25902591
}
25912592
}
25922593

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

0 commit comments

Comments
 (0)