Skip to content

Commit 7766795

Browse files
authored
feat(eg): add new data source to query quota (#7575)
1 parent 8572d26 commit 7766795

File tree

4 files changed

+288
-0
lines changed

4 files changed

+288
-0
lines changed

docs/data-sources/eg_quotas.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
subcategory: "EventGrid (EG)"
3+
layout: "huaweicloud"
4+
page_title: "HuaweiCloud: huaweicloud_eg_quotas"
5+
description: |-
6+
Use this data source to query EG quota of the current tenant within HuaweiCloud.
7+
---
8+
9+
# huaweicloud_eg_quotas
10+
11+
Use this data source to query EG quota of the current tenant within HuaweiCloud.
12+
13+
## Example Usage
14+
15+
```hcl
16+
data "huaweicloud_eg_quotas" "test" {}
17+
```
18+
19+
## Argument Reference
20+
21+
The following arguments are supported:
22+
23+
* `region` - (Optional, String) Specifies the region in which to query the resource.
24+
If omitted, the provider-level region will be used.
25+
26+
* `type` - (Optional, String) Specifies the quota of the resource type to be queried.
27+
28+
## Attribute Reference
29+
30+
In addition to all arguments above, the following attributes are exported:
31+
32+
* `id` - The data source ID.
33+
34+
* `quotas` - The list of resource quotas that matched filter parameters.
35+
The [quotas](#eg_quotas_attr) structure is documented below.
36+
37+
<a name="eg_quotas_attr"></a>
38+
The `quotas` block supports:
39+
40+
* `name` - The quota name.
41+
42+
* `type` - The quota type.
43+
44+
* `quota` - The quota of current tenant.
45+
46+
* `used` - The quota used by the current tenant.
47+
48+
* `max` - The maximum quota.
49+
50+
* `min` - The minimum quota.

huaweicloud/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,7 @@ func Provider() *schema.Provider {
982982
"huaweicloud_eg_event_sources": eg.DataSourceEventSources(),
983983
"huaweicloud_eg_event_streams": eg.DataSourceEventStreams(),
984984
"huaweicloud_eg_event_target_catalogs": eg.DataSourceEventTargetCatalogs(),
985+
"huaweicloud_eg_quotas": eg.DataSourceQuotas(),
985986

986987
// Professional EventRouter
987988
"huaweicloud_eg_eventrouter_availability_zones": eg.DataSourceEventRouterAvailabilityZones(),
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package eg
2+
3+
import (
4+
"regexp"
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 TestAccDataSourceEgQuotas_basic(t *testing.T) {
13+
var (
14+
all = "data.huaweicloud_eg_quotas.test"
15+
dc = acceptance.InitDataSourceCheck(all)
16+
17+
byType = "data.huaweicloud_eg_quotas.filter_by_type"
18+
dcByType = acceptance.InitDataSourceCheck(byType)
19+
)
20+
21+
resource.ParallelTest(t, resource.TestCase{
22+
PreCheck: func() {
23+
acceptance.TestAccPreCheck(t)
24+
},
25+
ProviderFactories: acceptance.TestAccProviderFactories,
26+
Steps: []resource.TestStep{
27+
{
28+
Config: testDataSourceEgQuotas_basic,
29+
Check: resource.ComposeTestCheckFunc(
30+
dc.CheckResourceExists(),
31+
resource.TestMatchResourceAttr(all, "quotas.#", regexp.MustCompile(`[1-9]\d*`)),
32+
resource.TestCheckResourceAttrSet(all, "quotas.#"),
33+
resource.TestCheckResourceAttrSet(all, "quotas.0.name"),
34+
resource.TestCheckResourceAttrSet(all, "quotas.0.type"),
35+
resource.TestCheckResourceAttrSet(all, "quotas.0.quota"),
36+
resource.TestCheckResourceAttrSet(all, "quotas.0.used"),
37+
resource.TestCheckResourceAttrSet(all, "quotas.0.max"),
38+
resource.TestCheckResourceAttrSet(all, "quotas.0.min"),
39+
40+
dcByType.CheckResourceExists(),
41+
resource.TestCheckOutput("is_type_filter_useful", "true"),
42+
),
43+
},
44+
},
45+
})
46+
}
47+
48+
const testDataSourceEgQuotas_basic = `
49+
data "huaweicloud_eg_quotas" "test" {}
50+
51+
# Filter by type
52+
locals {
53+
quota_type = try(data.huaweicloud_eg_quotas.test.quotas[0].type, "")
54+
}
55+
56+
data "huaweicloud_eg_quotas" "filter_by_type" {
57+
depends_on = [
58+
data.huaweicloud_eg_quotas.test
59+
]
60+
61+
type = local.quota_type
62+
}
63+
64+
locals {
65+
type_filter_result = [
66+
for v in try(data.huaweicloud_eg_quotas.filter_by_type.quotas[*].type) : v == local.quota_type
67+
]
68+
}
69+
70+
output "is_type_filter_useful" {
71+
value = length(local.type_filter_result) > 0 && alltrue(local.type_filter_result)
72+
}
73+
`
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package eg
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
8+
"github.com/hashicorp/go-multierror"
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+
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+
// @API EG GET /v1/{project_id}/quotas
20+
func DataSourceQuotas() *schema.Resource {
21+
return &schema.Resource{
22+
ReadContext: dataSourceEgQuotasRead,
23+
24+
Schema: map[string]*schema.Schema{
25+
"region": {
26+
Type: schema.TypeString,
27+
Optional: true,
28+
Computed: true,
29+
Description: `The region in which to query the resource.`,
30+
},
31+
"type": {
32+
Type: schema.TypeString,
33+
Optional: true,
34+
Description: `The quota of the resource type to be queried.`,
35+
},
36+
"quotas": {
37+
Type: schema.TypeList,
38+
Computed: true,
39+
Description: `The list of resource quotas that matched filter parameters.`,
40+
Elem: &schema.Resource{
41+
Schema: map[string]*schema.Schema{
42+
"name": {
43+
Type: schema.TypeString,
44+
Computed: true,
45+
Description: `The quota name.`,
46+
},
47+
"type": {
48+
Type: schema.TypeString,
49+
Computed: true,
50+
Description: `The quota type.`,
51+
},
52+
"quota": {
53+
Type: schema.TypeInt,
54+
Computed: true,
55+
Description: `The quota of current user.`,
56+
},
57+
"used": {
58+
Type: schema.TypeInt,
59+
Computed: true,
60+
Description: `The quota used by the current user.`,
61+
},
62+
"max": {
63+
Type: schema.TypeInt,
64+
Computed: true,
65+
Description: `The maximum quota.`,
66+
},
67+
"min": {
68+
Type: schema.TypeInt,
69+
Computed: true,
70+
Description: `The minimum quota.`,
71+
},
72+
},
73+
},
74+
},
75+
},
76+
}
77+
}
78+
79+
func buildQuotasQueryParams(d *schema.ResourceData) string {
80+
res := ""
81+
if quotaType, ok := d.GetOk("type"); ok {
82+
res = fmt.Sprintf("%s?type=%v", res, quotaType)
83+
}
84+
85+
return res
86+
}
87+
88+
func queryQuotas(client *golangsdk.ServiceClient, d *schema.ResourceData) ([]interface{}, error) {
89+
httpUrl := "v1/{project_id}/quotas"
90+
91+
listPath := client.Endpoint + httpUrl
92+
listPath = strings.ReplaceAll(listPath, "{project_id}", client.ProjectID)
93+
listPath += buildQuotasQueryParams(d)
94+
95+
opt := golangsdk.RequestOpts{
96+
KeepResponseBody: true,
97+
MoreHeaders: map[string]string{
98+
"Content-Type": "application/json",
99+
},
100+
}
101+
102+
requestResp, err := client.Request("GET", listPath, &opt)
103+
if err != nil {
104+
return nil, err
105+
}
106+
107+
respBody, err := utils.FlattenResponse(requestResp)
108+
if err != nil {
109+
return nil, err
110+
}
111+
112+
return utils.PathSearch("quotas.resources", respBody, make([]interface{}, 0)).([]interface{}), nil
113+
}
114+
115+
func flattenQuotas(quotas []interface{}) []interface{} {
116+
if len(quotas) < 1 {
117+
return nil
118+
}
119+
120+
result := make([]interface{}, 0, len(quotas))
121+
for _, resource := range quotas {
122+
result = append(result, map[string]interface{}{
123+
"name": utils.PathSearch("name", resource, nil),
124+
"type": utils.PathSearch("type", resource, nil),
125+
"quota": utils.PathSearch("quota", resource, nil),
126+
"used": utils.PathSearch("used", resource, nil),
127+
"max": utils.PathSearch("max", resource, nil),
128+
"min": utils.PathSearch("min", resource, nil),
129+
})
130+
}
131+
132+
return result
133+
}
134+
135+
func dataSourceEgQuotasRead(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
136+
var (
137+
cfg = meta.(*config.Config)
138+
region = cfg.GetRegion(d)
139+
)
140+
client, err := cfg.NewServiceClient("eg", region)
141+
if err != nil {
142+
return diag.Errorf("error creating EG client: %s", err)
143+
}
144+
145+
quotas, err := queryQuotas(client, d)
146+
if err != nil {
147+
return diag.Errorf("error getting EG quotas: %s", err)
148+
}
149+
150+
randUUID, err := uuid.GenerateUUID()
151+
if err != nil {
152+
return diag.Errorf("unable to generate ID: %s", err)
153+
}
154+
d.SetId(randUUID)
155+
156+
// Create the quotas structure with nested resources
157+
flattened := flattenQuotas(quotas)
158+
159+
mErr := multierror.Append(nil,
160+
d.Set("region", region),
161+
d.Set("quotas", flattened),
162+
)
163+
return diag.FromErr(mErr.ErrorOrNil())
164+
}

0 commit comments

Comments
 (0)