Skip to content

Commit e3a06e3

Browse files
lola98rileykarson
andauthored
Added CloudQuotas service and Create QuotaInfo Datasource (#10071)
* add quota info data source * add test and documention for quota_info data source * fix lint error * clean up * update test * manually import cloudquotas to terraform provider * Update mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb Co-authored-by: Riley Karson <[email protected]> * Update mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb Co-authored-by: Riley Karson <[email protected]> --------- Co-authored-by: Riley Karson <[email protected]>
1 parent 4555c33 commit e3a06e3

File tree

7 files changed

+407
-2
lines changed

7 files changed

+407
-2
lines changed
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright 2024 Google Inc.
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
14+
--- !ruby/object:Api::Product
15+
name: CloudQuotas
16+
display_name: Cloud Quotas
17+
versions:
18+
- !ruby/object:Api::Product::Version
19+
name: ga
20+
base_url: https://cloudquotas.googleapis.com/v1/
21+
scopes:
22+
- https://www.googleapis.com/auth/cloud-platform

mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt

+6-1
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ var ServicesListBeta = mapOf(
178178
"displayName" to "Cloudids",
179179
"path" to "./google-beta/services/cloudids"
180180
),
181+
"cloudquotas" to mapOf(
182+
"name" to "cloudquotas",
183+
"displayName" to "Cloudquotas",
184+
"path" to "./google-beta/services/cloudquotas"
185+
),
181186
"cloudrun" to mapOf(
182187
"name" to "cloudrun",
183188
"displayName" to "Cloudrun",
@@ -693,4 +698,4 @@ var ServicesListBeta = mapOf(
693698
"displayName" to "Workstations",
694699
"path" to "./google-beta/services/workstations"
695700
)
696-
)
701+
)

mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt

+6-1
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ var ServicesListGa = mapOf(
178178
"displayName" to "Cloudids",
179179
"path" to "./google/services/cloudids"
180180
),
181+
"cloudquotas" to mapOf(
182+
"name" to "cloudquotas",
183+
"displayName" to "Cloudquotas",
184+
"path" to "./google/services/cloudquotas"
185+
),
181186
"cloudrun" to mapOf(
182187
"name" to "cloudrun",
183188
"displayName" to "Cloudrun",
@@ -688,4 +693,4 @@ var ServicesListGa = mapOf(
688693
"displayName" to "Workstations",
689694
"path" to "./google/services/workstations"
690695
)
691-
)
696+
)

mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb

+4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ import (
1515
"github.com/hashicorp/terraform-provider-google/google/services/dataflow"
1616
"github.com/hashicorp/terraform-provider-google/google/services/servicenetworking"
1717
"github.com/hashicorp/terraform-provider-google/google/tpgiamresource"
18+
<% if version == 'ga' -%> // https://github.com/hashicorp/terraform-provider-google/issues/15633 for details
19+
"github.com/hashicorp/terraform-provider-google/google/services/cloudquotas"
20+
<% end -%>
1821
)
1922

2023
// Datasources
@@ -49,6 +52,7 @@ var handwrittenDatasources = map[string]*schema.Resource{
4952
"google_cloud_identity_groups": cloudidentity.DataSourceGoogleCloudIdentityGroups(),
5053
"google_cloud_identity_group_memberships": cloudidentity.DataSourceGoogleCloudIdentityGroupMemberships(),
5154
"google_cloud_identity_group_lookup": cloudidentity.DataSourceGoogleCloudIdentityGroupLookup(),
55+
"google_cloud_quotas_quota_info": cloudquotas.DataSourceGoogleCloudQuotasQuotaInfo(),
5256
"google_cloud_run_locations": cloudrun.DataSourceGoogleCloudRunLocations(),
5357
"google_cloud_run_service": cloudrun.DataSourceGoogleCloudRunService(),
5458
"google_cloud_run_v2_job": cloudrunv2.DataSourceGoogleCloudRunV2Job(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
package cloudquotas
4+
5+
import (
6+
"fmt"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
10+
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
11+
)
12+
13+
func DataSourceGoogleCloudQuotasQuotaInfo() *schema.Resource {
14+
return &schema.Resource{
15+
Read: dataSourceGoogleCloudQuotasQuotaInfoRead,
16+
17+
Schema: map[string]*schema.Schema{
18+
"parent": {
19+
Type: schema.TypeString,
20+
Required: true,
21+
},
22+
"service": {
23+
Type: schema.TypeString,
24+
Required: true,
25+
},
26+
"quota_id": {
27+
Type: schema.TypeString,
28+
Required: true,
29+
},
30+
"name": {
31+
Type: schema.TypeString,
32+
Computed: true,
33+
},
34+
"metric": {
35+
Type: schema.TypeString,
36+
Computed: true,
37+
},
38+
"is_precise": {
39+
Type: schema.TypeBool,
40+
Computed: true,
41+
},
42+
"refresh_interval": {
43+
Type: schema.TypeString,
44+
Computed: true,
45+
},
46+
"container_type": {
47+
Type: schema.TypeString,
48+
Computed: true,
49+
},
50+
"dimensions": {
51+
Type: schema.TypeList,
52+
Computed: true,
53+
Elem: &schema.Schema{Type: schema.TypeString},
54+
},
55+
"metric_display_name": {
56+
Type: schema.TypeString,
57+
Computed: true,
58+
},
59+
"quota_display_name": {
60+
Type: schema.TypeString,
61+
Computed: true,
62+
},
63+
"metric_unit": {
64+
Type: schema.TypeString,
65+
Computed: true,
66+
},
67+
"quota_increase_eligibility": {
68+
Type: schema.TypeList,
69+
Computed: true,
70+
Elem: &schema.Resource{
71+
Schema: map[string]*schema.Schema{
72+
"is_eligible": {
73+
Type: schema.TypeBool,
74+
Computed: true,
75+
},
76+
"ineligibility_reason": {
77+
Type: schema.TypeString,
78+
Computed: true,
79+
},
80+
},
81+
},
82+
},
83+
"is_fixed": {
84+
Type: schema.TypeBool,
85+
Computed: true,
86+
},
87+
"dimensions_infos": {
88+
Type: schema.TypeList,
89+
Computed: true,
90+
Elem: &schema.Resource{
91+
Schema: map[string]*schema.Schema{
92+
"dimensions": {
93+
Type: schema.TypeMap,
94+
Computed: true,
95+
},
96+
"details": {
97+
Type: schema.TypeList,
98+
Computed: true,
99+
Elem: &schema.Resource{
100+
Schema: map[string]*schema.Schema{
101+
"value": {
102+
Type: schema.TypeString,
103+
Computed: true,
104+
},
105+
},
106+
},
107+
},
108+
"applicable_locations": {
109+
Type: schema.TypeList,
110+
Computed: true,
111+
Elem: &schema.Schema{Type: schema.TypeString},
112+
},
113+
},
114+
},
115+
},
116+
"is_concurrent": {
117+
Type: schema.TypeBool,
118+
Computed: true,
119+
},
120+
"service_request_quota_uri": {
121+
Type: schema.TypeString,
122+
Computed: true,
123+
},
124+
},
125+
UseJSONNumber: true,
126+
}
127+
}
128+
129+
func dataSourceGoogleCloudQuotasQuotaInfoRead(d *schema.ResourceData, meta interface{}) error {
130+
config := meta.(*transport_tpg.Config)
131+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
132+
if err != nil {
133+
return err
134+
}
135+
136+
url, err := tpgresource.ReplaceVars(d, config, "{{CloudQuotasBasePath}}{{parent}}/locations/global/services/{{service}}/quotaInfos/{{quota_id}}")
137+
if err != nil {
138+
return fmt.Errorf("error setting api endpoint")
139+
}
140+
141+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
142+
Config: config,
143+
Method: "GET",
144+
RawURL: url,
145+
UserAgent: userAgent,
146+
})
147+
148+
if err != nil {
149+
return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("CloudQuotasQuotaInfo %q", d.Id()))
150+
}
151+
152+
if err := d.Set("name", res["name"]); err != nil {
153+
return fmt.Errorf("error reading QuotaInfo name: %s", err)
154+
}
155+
if err := d.Set("quota_id", res["quotaId"]); err != nil {
156+
return fmt.Errorf("error reading QuotaInfo quota_id: %s", err)
157+
}
158+
if err := d.Set("metric", res["metric"]); err != nil {
159+
return fmt.Errorf("error reading QuotaInfo metric: %s", err)
160+
}
161+
if err := d.Set("service", res["service"]); err != nil {
162+
return fmt.Errorf("error reading QuotaInfo service: %s", err)
163+
}
164+
if err := d.Set("is_precise", res["isPrecise"]); err != nil {
165+
return fmt.Errorf("error reading QuotaInfo is_precise: %s", err)
166+
}
167+
if err := d.Set("refresh_interval", res["refreshInterval"]); err != nil {
168+
return fmt.Errorf("error reading QuotaInfo refresh_interval: %s", err)
169+
}
170+
if err := d.Set("container_type", res["containerType"]); err != nil {
171+
return fmt.Errorf("error reading QuotaInfo container_type: %s", err)
172+
}
173+
if err := d.Set("dimensions", res["dimensions"]); err != nil {
174+
return fmt.Errorf("error reading QuotaInfo dimensions: %s", err)
175+
}
176+
if err := d.Set("metric_display_name", res["metricDisplayName"]); err != nil {
177+
return fmt.Errorf("error reading QuotaInfo metric_display_name: %s", err)
178+
}
179+
if err := d.Set("quota_display_name", res["quotaDisplayName"]); err != nil {
180+
return fmt.Errorf("error reading QuotaInfo quota_display_name: %s", err)
181+
}
182+
if err := d.Set("metric_unit", res["metricUnit"]); err != nil {
183+
return fmt.Errorf("error reading QuotaInfo metric_unit: %s", err)
184+
}
185+
if err := d.Set("quota_increase_eligibility", flattenCloudQuotasQuotaInfoQuotaIncreaseEligibility(res["quotaIncreaseEligibility"], d, config)); err != nil {
186+
return fmt.Errorf("error reading QuotaInfo quota_increase_eligibility: %s", err)
187+
}
188+
if err := d.Set("is_fixed", res["isFixed"]); err != nil {
189+
return fmt.Errorf("error reading QuotaInfo is_fixed: %s", err)
190+
}
191+
if err := d.Set("dimensions_infos", flattenCloudQuotasQuotaInfoDimensionsInfos(res["dimensionsInfos"], d, config)); err != nil {
192+
return fmt.Errorf("error reading QuotaInfo dimensions_infos: %s", err)
193+
}
194+
if err := d.Set("is_concurrent", res["isConcurrent"]); err != nil {
195+
return fmt.Errorf("error reading QuotaInfo is_concurrent: %s", err)
196+
}
197+
if err := d.Set("service_request_quota_uri", res["serviceRequestQuotaUri"]); err != nil {
198+
return fmt.Errorf("error reading QuotaInfo service_request_quota_uri: %s", err)
199+
}
200+
201+
d.SetId(res["name"].(string))
202+
return nil
203+
}
204+
205+
func flattenCloudQuotasQuotaInfoQuotaIncreaseEligibility(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
206+
if v == nil {
207+
return nil
208+
}
209+
original := v.(map[string]interface{})
210+
if len(original) == 0 {
211+
return nil
212+
}
213+
transformed := make(map[string]interface{})
214+
transformed["is_eligible"] = original["is_eligible"]
215+
transformed["ineligibility_reason"] = original["ineligibility_reason"]
216+
return []interface{}{transformed}
217+
}
218+
219+
func flattenCloudQuotasQuotaInfoDimensionsInfos(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) []interface{} {
220+
if v == nil {
221+
return make([]interface{}, 0)
222+
}
223+
224+
original := v.([]interface{})
225+
dimensionsInfos := make([]interface{}, 0, len(original))
226+
227+
for _, raw := range original {
228+
data := make(map[string]interface{})
229+
data["details"] = flattenCloudQuotasQuotaInfoDetails(raw.(map[string]interface{})["details"], d, config)
230+
data["applicable_locations"] = raw.(map[string]interface{})["applicableLocations"]
231+
data["dimensions"] = raw.(map[string]interface{})["dimensions"]
232+
233+
dimensionsInfos = append(dimensionsInfos, data)
234+
}
235+
return dimensionsInfos
236+
}
237+
238+
func flattenCloudQuotasQuotaInfoDetails(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
239+
original, ok := v.(map[string]interface{})
240+
if !ok || len(original) == 0 {
241+
return nil
242+
}
243+
244+
return []interface{}{
245+
map[string]interface{}{"value": original["value"]},
246+
}
247+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
package cloudquotas_test
4+
5+
import (
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
9+
"github.com/hashicorp/terraform-provider-google/google/acctest"
10+
"github.com/hashicorp/terraform-provider-google/google/envvar"
11+
)
12+
13+
func TestAccDataSourceGoogleQuotaInfo_basic(t *testing.T) {
14+
t.Parallel()
15+
16+
resourceName := "data.google_cloud_quotas_quota_info.my_quota_info"
17+
service := "compute.googleapis.com"
18+
quotaId := "CPUS-per-project-region"
19+
20+
context := map[string]interface{}{
21+
"project": envvar.GetTestProjectFromEnv(),
22+
"service": service,
23+
"quota_id": quotaId,
24+
}
25+
26+
acctest.VcrTest(t, resource.TestCase{
27+
PreCheck: func() { acctest.AccTestPreCheck(t) },
28+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
29+
Steps: []resource.TestStep{
30+
{
31+
Config: testAccDataSourceGoogleQuotaInfo_basic(context),
32+
Check: resource.ComposeTestCheckFunc(
33+
resource.TestCheckResourceAttrSet(resourceName, "name"),
34+
resource.TestCheckResourceAttr(resourceName, "quota_id", quotaId),
35+
resource.TestCheckResourceAttr(resourceName, "metric", "compute.googleapis.com/cpus"),
36+
resource.TestCheckResourceAttr(resourceName, "service", service),
37+
resource.TestCheckResourceAttrSet(resourceName, "is_precise"),
38+
resource.TestCheckResourceAttr(resourceName, "container_type", "PROJECT"),
39+
resource.TestCheckResourceAttr(resourceName, "dimensions.0", "region"),
40+
resource.TestCheckResourceAttr(resourceName, "metric_display_name", "CPUs"),
41+
resource.TestCheckResourceAttr(resourceName, "quota_display_name", "CPUs"),
42+
resource.TestCheckResourceAttrSet(resourceName, "metric_unit"),
43+
resource.TestCheckResourceAttrSet(resourceName, "quota_increase_eligibility.0.is_eligible"),
44+
resource.TestCheckResourceAttrSet(resourceName, "dimensions_infos.0.dimensions.region"),
45+
resource.TestCheckResourceAttrSet(resourceName, "dimensions_infos.0.details.0.value"),
46+
resource.TestCheckResourceAttrSet(resourceName, "dimensions_infos.0.applicable_locations.0"),
47+
),
48+
},
49+
},
50+
})
51+
}
52+
53+
func testAccDataSourceGoogleQuotaInfo_basic(context map[string]interface{}) string {
54+
return acctest.Nprintf(`
55+
data "google_cloud_quotas_quota_info" "my_quota_info" {
56+
parent = "projects/%{project}"
57+
quota_id = "%{quota_id}"
58+
service = "%{service}"
59+
}
60+
`, context)
61+
}

0 commit comments

Comments
 (0)