Skip to content

Commit eb3adc8

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

File tree

5 files changed

+277
-8
lines changed

5 files changed

+277
-8
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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 operate event subscription status. Deleting this resource
14+
will 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.
46+
only enterprise project can use this.
47+
48+
## Attribute Reference
49+
50+
In addition to all arguments above, the following attributes are exported:
51+
52+
* `id` - The resource ID.

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_batch_action": eg.ResourceEventSubscriptionBatchAction(),
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: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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 TestAccEventSubscriptionBatchAction_basic(t *testing.T) {
13+
var (
14+
rcName = "huaweicloud_eg_event_subscription_batch_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: testEventSubscriptionBatchAction_basic(),
29+
Check: resource.ComposeTestCheckFunc(
30+
resource.TestCheckResourceAttr(rcName, "operation", "ENABLE"),
31+
resource.TestCheckResourceAttr(rcName, "subscription_ids.#", "1"),
32+
),
33+
},
34+
},
35+
})
36+
}
37+
38+
func testEventSubscriptionBatchAction_basic() string {
39+
return fmt.Sprintf(`
40+
resource "huaweicloud_eg_event_subscription_batch_action" "test" {
41+
subscription_ids = ["%[1]s"]
42+
operation = "ENABLE"
43+
}
44+
`, acceptance.HW_EG_EVENT_SUBSCRIPTION_ID)
45+
}
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.`,
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("error creating EG event subscription action: %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 operate 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)