Skip to content

Commit

Permalink
Added CloudQuotas service and Create QuotaInfo Datasource (#10071)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
lola98 and rileykarson authored Mar 13, 2024
1 parent 4555c33 commit e3a06e3
Show file tree
Hide file tree
Showing 7 changed files with 407 additions and 2 deletions.
22 changes: 22 additions & 0 deletions mmv1/products/cloudquotas/product.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2024 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

--- !ruby/object:Api::Product
name: CloudQuotas
display_name: Cloud Quotas
versions:
- !ruby/object:Api::Product::Version
name: ga
base_url: https://cloudquotas.googleapis.com/v1/
scopes:
- https://www.googleapis.com/auth/cloud-platform
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ var ServicesListBeta = mapOf(
"displayName" to "Cloudids",
"path" to "./google-beta/services/cloudids"
),
"cloudquotas" to mapOf(
"name" to "cloudquotas",
"displayName" to "Cloudquotas",
"path" to "./google-beta/services/cloudquotas"
),
"cloudrun" to mapOf(
"name" to "cloudrun",
"displayName" to "Cloudrun",
Expand Down Expand Up @@ -693,4 +698,4 @@ var ServicesListBeta = mapOf(
"displayName" to "Workstations",
"path" to "./google-beta/services/workstations"
)
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ var ServicesListGa = mapOf(
"displayName" to "Cloudids",
"path" to "./google/services/cloudids"
),
"cloudquotas" to mapOf(
"name" to "cloudquotas",
"displayName" to "Cloudquotas",
"path" to "./google/services/cloudquotas"
),
"cloudrun" to mapOf(
"name" to "cloudrun",
"displayName" to "Cloudrun",
Expand Down Expand Up @@ -688,4 +693,4 @@ var ServicesListGa = mapOf(
"displayName" to "Workstations",
"path" to "./google/services/workstations"
)
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import (
"github.com/hashicorp/terraform-provider-google/google/services/dataflow"
"github.com/hashicorp/terraform-provider-google/google/services/servicenetworking"
"github.com/hashicorp/terraform-provider-google/google/tpgiamresource"
<% if version == 'ga' -%> // https://github.com/hashicorp/terraform-provider-google/issues/15633 for details
"github.com/hashicorp/terraform-provider-google/google/services/cloudquotas"
<% end -%>
)

// Datasources
Expand Down Expand Up @@ -49,6 +52,7 @@ var handwrittenDatasources = map[string]*schema.Resource{
"google_cloud_identity_groups": cloudidentity.DataSourceGoogleCloudIdentityGroups(),
"google_cloud_identity_group_memberships": cloudidentity.DataSourceGoogleCloudIdentityGroupMemberships(),
"google_cloud_identity_group_lookup": cloudidentity.DataSourceGoogleCloudIdentityGroupLookup(),
"google_cloud_quotas_quota_info": cloudquotas.DataSourceGoogleCloudQuotasQuotaInfo(),
"google_cloud_run_locations": cloudrun.DataSourceGoogleCloudRunLocations(),
"google_cloud_run_service": cloudrun.DataSourceGoogleCloudRunService(),
"google_cloud_run_v2_job": cloudrunv2.DataSourceGoogleCloudRunV2Job(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package cloudquotas

import (
"fmt"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
)

func DataSourceGoogleCloudQuotasQuotaInfo() *schema.Resource {
return &schema.Resource{
Read: dataSourceGoogleCloudQuotasQuotaInfoRead,

Schema: map[string]*schema.Schema{
"parent": {
Type: schema.TypeString,
Required: true,
},
"service": {
Type: schema.TypeString,
Required: true,
},
"quota_id": {
Type: schema.TypeString,
Required: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"metric": {
Type: schema.TypeString,
Computed: true,
},
"is_precise": {
Type: schema.TypeBool,
Computed: true,
},
"refresh_interval": {
Type: schema.TypeString,
Computed: true,
},
"container_type": {
Type: schema.TypeString,
Computed: true,
},
"dimensions": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"metric_display_name": {
Type: schema.TypeString,
Computed: true,
},
"quota_display_name": {
Type: schema.TypeString,
Computed: true,
},
"metric_unit": {
Type: schema.TypeString,
Computed: true,
},
"quota_increase_eligibility": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"is_eligible": {
Type: schema.TypeBool,
Computed: true,
},
"ineligibility_reason": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"is_fixed": {
Type: schema.TypeBool,
Computed: true,
},
"dimensions_infos": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"dimensions": {
Type: schema.TypeMap,
Computed: true,
},
"details": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"value": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"applicable_locations": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
"is_concurrent": {
Type: schema.TypeBool,
Computed: true,
},
"service_request_quota_uri": {
Type: schema.TypeString,
Computed: true,
},
},
UseJSONNumber: true,
}
}

func dataSourceGoogleCloudQuotasQuotaInfoRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
return err
}

url, err := tpgresource.ReplaceVars(d, config, "{{CloudQuotasBasePath}}{{parent}}/locations/global/services/{{service}}/quotaInfos/{{quota_id}}")
if err != nil {
return fmt.Errorf("error setting api endpoint")
}

res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
Config: config,
Method: "GET",
RawURL: url,
UserAgent: userAgent,
})

if err != nil {
return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("CloudQuotasQuotaInfo %q", d.Id()))
}

if err := d.Set("name", res["name"]); err != nil {
return fmt.Errorf("error reading QuotaInfo name: %s", err)
}
if err := d.Set("quota_id", res["quotaId"]); err != nil {
return fmt.Errorf("error reading QuotaInfo quota_id: %s", err)
}
if err := d.Set("metric", res["metric"]); err != nil {
return fmt.Errorf("error reading QuotaInfo metric: %s", err)
}
if err := d.Set("service", res["service"]); err != nil {
return fmt.Errorf("error reading QuotaInfo service: %s", err)
}
if err := d.Set("is_precise", res["isPrecise"]); err != nil {
return fmt.Errorf("error reading QuotaInfo is_precise: %s", err)
}
if err := d.Set("refresh_interval", res["refreshInterval"]); err != nil {
return fmt.Errorf("error reading QuotaInfo refresh_interval: %s", err)
}
if err := d.Set("container_type", res["containerType"]); err != nil {
return fmt.Errorf("error reading QuotaInfo container_type: %s", err)
}
if err := d.Set("dimensions", res["dimensions"]); err != nil {
return fmt.Errorf("error reading QuotaInfo dimensions: %s", err)
}
if err := d.Set("metric_display_name", res["metricDisplayName"]); err != nil {
return fmt.Errorf("error reading QuotaInfo metric_display_name: %s", err)
}
if err := d.Set("quota_display_name", res["quotaDisplayName"]); err != nil {
return fmt.Errorf("error reading QuotaInfo quota_display_name: %s", err)
}
if err := d.Set("metric_unit", res["metricUnit"]); err != nil {
return fmt.Errorf("error reading QuotaInfo metric_unit: %s", err)
}
if err := d.Set("quota_increase_eligibility", flattenCloudQuotasQuotaInfoQuotaIncreaseEligibility(res["quotaIncreaseEligibility"], d, config)); err != nil {
return fmt.Errorf("error reading QuotaInfo quota_increase_eligibility: %s", err)
}
if err := d.Set("is_fixed", res["isFixed"]); err != nil {
return fmt.Errorf("error reading QuotaInfo is_fixed: %s", err)
}
if err := d.Set("dimensions_infos", flattenCloudQuotasQuotaInfoDimensionsInfos(res["dimensionsInfos"], d, config)); err != nil {
return fmt.Errorf("error reading QuotaInfo dimensions_infos: %s", err)
}
if err := d.Set("is_concurrent", res["isConcurrent"]); err != nil {
return fmt.Errorf("error reading QuotaInfo is_concurrent: %s", err)
}
if err := d.Set("service_request_quota_uri", res["serviceRequestQuotaUri"]); err != nil {
return fmt.Errorf("error reading QuotaInfo service_request_quota_uri: %s", err)
}

d.SetId(res["name"].(string))
return nil
}

func flattenCloudQuotasQuotaInfoQuotaIncreaseEligibility(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["is_eligible"] = original["is_eligible"]
transformed["ineligibility_reason"] = original["ineligibility_reason"]
return []interface{}{transformed}
}

func flattenCloudQuotasQuotaInfoDimensionsInfos(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) []interface{} {
if v == nil {
return make([]interface{}, 0)
}

original := v.([]interface{})
dimensionsInfos := make([]interface{}, 0, len(original))

for _, raw := range original {
data := make(map[string]interface{})
data["details"] = flattenCloudQuotasQuotaInfoDetails(raw.(map[string]interface{})["details"], d, config)
data["applicable_locations"] = raw.(map[string]interface{})["applicableLocations"]
data["dimensions"] = raw.(map[string]interface{})["dimensions"]

dimensionsInfos = append(dimensionsInfos, data)
}
return dimensionsInfos
}

func flattenCloudQuotasQuotaInfoDetails(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
original, ok := v.(map[string]interface{})
if !ok || len(original) == 0 {
return nil
}

return []interface{}{
map[string]interface{}{"value": original["value"]},
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package cloudquotas_test

import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-provider-google/google/acctest"
"github.com/hashicorp/terraform-provider-google/google/envvar"
)

func TestAccDataSourceGoogleQuotaInfo_basic(t *testing.T) {
t.Parallel()

resourceName := "data.google_cloud_quotas_quota_info.my_quota_info"
service := "compute.googleapis.com"
quotaId := "CPUS-per-project-region"

context := map[string]interface{}{
"project": envvar.GetTestProjectFromEnv(),
"service": service,
"quota_id": quotaId,
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
Steps: []resource.TestStep{
{
Config: testAccDataSourceGoogleQuotaInfo_basic(context),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(resourceName, "name"),
resource.TestCheckResourceAttr(resourceName, "quota_id", quotaId),
resource.TestCheckResourceAttr(resourceName, "metric", "compute.googleapis.com/cpus"),
resource.TestCheckResourceAttr(resourceName, "service", service),
resource.TestCheckResourceAttrSet(resourceName, "is_precise"),
resource.TestCheckResourceAttr(resourceName, "container_type", "PROJECT"),
resource.TestCheckResourceAttr(resourceName, "dimensions.0", "region"),
resource.TestCheckResourceAttr(resourceName, "metric_display_name", "CPUs"),
resource.TestCheckResourceAttr(resourceName, "quota_display_name", "CPUs"),
resource.TestCheckResourceAttrSet(resourceName, "metric_unit"),
resource.TestCheckResourceAttrSet(resourceName, "quota_increase_eligibility.0.is_eligible"),
resource.TestCheckResourceAttrSet(resourceName, "dimensions_infos.0.dimensions.region"),
resource.TestCheckResourceAttrSet(resourceName, "dimensions_infos.0.details.0.value"),
resource.TestCheckResourceAttrSet(resourceName, "dimensions_infos.0.applicable_locations.0"),
),
},
},
})
}

func testAccDataSourceGoogleQuotaInfo_basic(context map[string]interface{}) string {
return acctest.Nprintf(`
data "google_cloud_quotas_quota_info" "my_quota_info" {
parent = "projects/%{project}"
quota_id = "%{quota_id}"
service = "%{service}"
}
`, context)
}
Loading

0 comments on commit e3a06e3

Please sign in to comment.