Skip to content

Commit 9a3bf31

Browse files
Added a new datasource for fetching the list of supported alloydb database flags in a location (#7679) (#14365)
* Added validation for "type" in cloud_sql_user_resource for preventing user from setting "password" or "host" for CLOUD_IAM_USER and CLOUD_IAM_SERVICE_ACCOUNT user types. * Removed validation and added documentation to prevent setting of host or password field for CLOUD_IAM_USER and CLOUD_IAM_SERVICE_ACCOUNT * added new datasource for fetching all the alloydb supported database flags in a location. * added new datasource for fetching all the alloydb supported database flags in a location. * Using go client for api calls * using v1 and v1beta go clients for GA and beta providers respectively * Revert "added new datasource for fetching all the alloydb supported database flags in a location." This reverts commit b5f728edb3b92adfc7a38d856b02f2f79f48b20d. * making http calls using magic modules send request insted of alloydb go client Signed-off-by: Modular Magician <[email protected]>
1 parent 410d23f commit 9a3bf31

6 files changed

+350
-1
lines changed

.changelog/7679.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:none
2+
A new datasource for fetching the list of alloydb supported database flags in a location.
3+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
package google
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
7+
)
8+
9+
func DataSourceAlloydbSupportedDatabaseFlags() *schema.Resource {
10+
11+
return &schema.Resource{
12+
Read: dataSourceAlloydbSupportedDatabaseFlagsRead,
13+
14+
Schema: map[string]*schema.Schema{
15+
"project": {
16+
Type: schema.TypeString,
17+
Optional: true,
18+
Description: `Project ID of the project.`,
19+
},
20+
"location": {
21+
Type: schema.TypeString,
22+
Required: true,
23+
Description: `The canonical id for the location. For example: "us-east1".`,
24+
},
25+
"supported_database_flags": {
26+
Type: schema.TypeList,
27+
Computed: true,
28+
Elem: &schema.Resource{
29+
Schema: map[string]*schema.Schema{
30+
"name": {
31+
Type: schema.TypeString,
32+
Computed: true,
33+
Optional: true,
34+
Description: `The name of the flag resource, following Google Cloud conventions, e.g.: * projects/{project}/locations/{location}/flags/{flag} This field currently has no semantic meaning.`,
35+
},
36+
"flag_name": {
37+
Type: schema.TypeString,
38+
Computed: true,
39+
Optional: true,
40+
Description: `The name of the database flag, e.g. "max_allowed_packets". The is a possibly key for the Instance.database_flags map field.`,
41+
},
42+
"value_type": {
43+
Type: schema.TypeString,
44+
Computed: true,
45+
Optional: true,
46+
Description: `ValueType describes the semantic type of the value that the flag accepts. The supported values are:- 'VALUE_TYPE_UNSPECIFIED', 'STRING', 'INTEGER', 'FLOAT', 'NONE'.`,
47+
},
48+
"accepts_multiple_values": {
49+
Type: schema.TypeBool,
50+
Computed: true,
51+
Optional: true,
52+
Description: `Whether the database flag accepts multiple values. If true, a comma-separated list of stringified values may be specified.`,
53+
},
54+
"supported_db_versions": {
55+
Type: schema.TypeList,
56+
Computed: true,
57+
Optional: true,
58+
Description: `Major database engine versions for which this flag is supported. Supported values are:- 'DATABASE_VERSION_UNSPECIFIED', and 'POSTGRES_14'.`,
59+
Elem: &schema.Schema{Type: schema.TypeString},
60+
},
61+
"requires_db_restart": {
62+
Type: schema.TypeBool,
63+
Computed: true,
64+
Optional: true,
65+
Description: `Whether setting or updating this flag on an Instance requires a database restart. If a flag that requires database restart is set, the backend will automatically restart the database (making sure to satisfy any availability SLO's).`,
66+
},
67+
"string_restrictions": {
68+
Type: schema.TypeList,
69+
Computed: true,
70+
Optional: true,
71+
Description: `Restriction on STRING type value.`,
72+
MaxItems: 1,
73+
Elem: &schema.Resource{
74+
Schema: map[string]*schema.Schema{
75+
"allowed_values": {
76+
Type: schema.TypeList,
77+
Computed: true,
78+
Optional: true,
79+
Description: `The list of allowed values, if bounded. This field will be empty if there is a unbounded number of allowed values.`,
80+
Elem: &schema.Schema{Type: schema.TypeString},
81+
},
82+
},
83+
},
84+
},
85+
"integer_restrictions": {
86+
Type: schema.TypeList,
87+
Computed: true,
88+
Optional: true,
89+
Description: `Restriction on INTEGER type value.`,
90+
MaxItems: 1,
91+
Elem: &schema.Resource{
92+
Schema: map[string]*schema.Schema{
93+
"min_value": {
94+
Type: schema.TypeString,
95+
Computed: true,
96+
Optional: true,
97+
Description: `The minimum value that can be specified, if applicable.`,
98+
},
99+
"max_value": {
100+
Type: schema.TypeString,
101+
Computed: true,
102+
Optional: true,
103+
Description: `The maximum value that can be specified, if applicable.`,
104+
},
105+
},
106+
},
107+
},
108+
},
109+
},
110+
},
111+
},
112+
}
113+
}
114+
115+
func dataSourceAlloydbSupportedDatabaseFlagsRead(d *schema.ResourceData, meta interface{}) error {
116+
config := meta.(*Config)
117+
userAgent, err := generateUserAgentString(d, config.UserAgent)
118+
if err != nil {
119+
return err
120+
}
121+
location := d.Get("location").(string)
122+
123+
billingProject := ""
124+
125+
project, err := getProject(d, config)
126+
if err != nil {
127+
return fmt.Errorf("Error fetching project for Cluster: %s", err)
128+
}
129+
billingProject = project
130+
131+
// err == nil indicates that the billing_project value was found
132+
if bp, err := getBillingProject(d, config); err == nil {
133+
billingProject = bp
134+
}
135+
136+
url, err := ReplaceVars(d, config, "{{AlloydbBasePath}}projects/{{project}}/locations/{{location}}/supportedDatabaseFlags")
137+
if err != nil {
138+
return fmt.Errorf("Error setting api endpoint")
139+
}
140+
res, err := SendRequest(config, "GET", billingProject, url, userAgent, nil)
141+
if err != nil {
142+
return handleNotFoundError(err, d, fmt.Sprintf("SupportedDatabaseFlags %q", d.Id()))
143+
}
144+
var supportedDatabaseFlags []map[string]interface{}
145+
for {
146+
result := res["supportedDatabaseFlags"].([]interface{})
147+
for _, dbFlag := range result {
148+
supportedDatabaseFlag := make(map[string]interface{})
149+
flag := dbFlag.(map[string]interface{})
150+
if flag["name"] != nil {
151+
supportedDatabaseFlag["name"] = flag["name"].(string)
152+
}
153+
if flag["flagName"] != nil {
154+
supportedDatabaseFlag["flag_name"] = flag["flagName"].(string)
155+
}
156+
if flag["valueType"] != nil {
157+
supportedDatabaseFlag["value_type"] = flag["valueType"].(string)
158+
}
159+
if flag["acceptsMultipleValues"] != nil {
160+
supportedDatabaseFlag["accepts_multiple_values"] = flag["acceptsMultipleValues"].(bool)
161+
}
162+
if flag["requiresDbRestart"] != nil {
163+
supportedDatabaseFlag["requires_db_restart"] = flag["requiresDbRestart"].(bool)
164+
}
165+
if flag["supportedDbVersions"] != nil {
166+
dbVersions := make([]string, 0, len(flag["supportedDbVersions"].([]interface{})))
167+
for _, supDbVer := range flag["supportedDbVersions"].([]interface{}) {
168+
dbVersions = append(dbVersions, supDbVer.(string))
169+
}
170+
supportedDatabaseFlag["supported_db_versions"] = dbVersions
171+
}
172+
173+
if flag["stringRestrictions"] != nil {
174+
restrictions := make([]map[string][]string, 0, 1)
175+
fetchedAllowedValues := flag["stringRestrictions"].(map[string]interface{})["allowedValues"]
176+
if fetchedAllowedValues != nil {
177+
allowedValues := make([]string, 0, len(fetchedAllowedValues.([]interface{})))
178+
for _, val := range fetchedAllowedValues.([]interface{}) {
179+
allowedValues = append(allowedValues, val.(string))
180+
}
181+
stringRestrictions := map[string][]string{
182+
"allowed_values": allowedValues,
183+
}
184+
restrictions = append(restrictions, stringRestrictions)
185+
supportedDatabaseFlag["string_restrictions"] = restrictions
186+
}
187+
}
188+
if flag["integerRestrictions"] != nil {
189+
restrictions := make([]map[string]string, 0, 1)
190+
minValue := flag["integerRestrictions"].(map[string]interface{})["minValue"].(string)
191+
maxValue := flag["integerRestrictions"].(map[string]interface{})["maxValue"].(string)
192+
integerRestrictions := map[string]string{
193+
"min_value": minValue,
194+
"max_value": maxValue,
195+
}
196+
restrictions = append(restrictions, integerRestrictions)
197+
supportedDatabaseFlag["integer_restrictions"] = restrictions
198+
}
199+
supportedDatabaseFlags = append(supportedDatabaseFlags, supportedDatabaseFlag)
200+
}
201+
if res["pageToken"] == nil || res["pageToken"].(string) == "" {
202+
break
203+
}
204+
url, err = ReplaceVars(d, config, "{{AlloydbBasePath}}projects/{{project}}/locations/{{location}}/supportedDatabaseFlags?pageToken="+res["nextPageToken"].(string))
205+
if err != nil {
206+
return fmt.Errorf("Error setting api endpoint")
207+
}
208+
res, err = SendRequest(config, "GET", billingProject, url, userAgent, nil)
209+
if err != nil {
210+
return handleNotFoundError(err, d, fmt.Sprintf("SupportedDatabaseFlags %q", d.Id()))
211+
}
212+
}
213+
if err := d.Set("supported_database_flags", supportedDatabaseFlags); err != nil {
214+
return fmt.Errorf("Error setting supported_database_flags: %s", err)
215+
}
216+
d.SetId(fmt.Sprintf("projects/%s/locations/%s/supportedDbFlags", project, location))
217+
return nil
218+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package google
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"strconv"
7+
"testing"
8+
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
11+
)
12+
13+
func TestAccDataSourceAlloydbSupportedDatabaseFlags_basic(t *testing.T) {
14+
t.Parallel()
15+
16+
context := map[string]interface{}{
17+
"random_suffix": RandString(t, 10),
18+
}
19+
20+
VcrTest(t, resource.TestCase{
21+
PreCheck: func() { AccTestPreCheck(t) },
22+
Providers: TestAccProviders,
23+
CheckDestroy: testAccSqlDatabaseDestroyProducer(t),
24+
Steps: []resource.TestStep{
25+
{
26+
Config: testAccDataSourceAlloydbSupportedDatabaseFlags_basic(context),
27+
Check: resource.ComposeTestCheckFunc(
28+
validateAlloydbSupportedDatabaseFlagsResult(
29+
"data.google_alloydb_supported_database_flags.qa",
30+
),
31+
),
32+
},
33+
},
34+
})
35+
}
36+
37+
func testAccDataSourceAlloydbSupportedDatabaseFlags_basic(context map[string]interface{}) string {
38+
return Nprintf(`
39+
data "google_alloydb_supported_database_flags" "qa" {
40+
location = "us-central1"
41+
}
42+
`, context)
43+
}
44+
45+
func validateAlloydbSupportedDatabaseFlagsResult(dataSourceName string) func(*terraform.State) error {
46+
return func(s *terraform.State) error {
47+
ds, ok := s.RootModule().Resources[dataSourceName]
48+
if !ok {
49+
return fmt.Errorf("can't find %s in state", dataSourceName)
50+
}
51+
52+
var dsAttr map[string]string
53+
dsAttr = ds.Primary.Attributes
54+
55+
totalFlags, err := strconv.Atoi(dsAttr["supported_database_flags.#"])
56+
if err != nil {
57+
return errors.New("Couldn't convert length of flags list to integer")
58+
}
59+
if totalFlags == 0 {
60+
return errors.New("No supported database flags are fetched from location 'us-central1'")
61+
}
62+
for i := 0; i < totalFlags; i++ {
63+
if dsAttr["supported_database_flags."+strconv.Itoa(i)+".name"] == "" {
64+
return errors.New("name parameter is not set for the flag")
65+
}
66+
if dsAttr["supported_database_flags."+strconv.Itoa(i)+".flag_name"] == "" {
67+
return errors.New("flag_name parameter is not set for the flag")
68+
}
69+
if len(dsAttr["supported_database_flags."+strconv.Itoa(i)+".string_restrictions"]) > 0 && len(dsAttr["supported_database_flags."+strconv.Itoa(i)+".integer_restrictions"]) > 0 {
70+
return errors.New("Both string restriction and integer restriction cannot be set for a union restriction field")
71+
}
72+
}
73+
return nil
74+
}
75+
}

google/data_source_sql_databases_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ func checkDatabaseFieldsMatchForDataSourceStateAndResourceState(dsAttr, rsAttr m
120120
}
121121

122122
if index == "-1" {
123-
return errors.New("The newly created intance is not found in the data source")
123+
return errors.New("The newly created instance is not found in the data source")
124124
}
125125

126126
errMsg := ""

google/provider.go

+1
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,7 @@ func Provider() *schema.Provider {
578578
"google_access_approval_project_service_account": DataSourceAccessApprovalProjectServiceAccount(),
579579
"google_active_folder": DataSourceGoogleActiveFolder(),
580580
"google_alloydb_locations": DataSourceAlloydbLocations(),
581+
"google_alloydb_supported_database_flags": DataSourceAlloydbSupportedDatabaseFlags(),
581582
"google_artifact_registry_repository": DataSourceArtifactRegistryRepository(),
582583
"google_app_engine_default_service_account": DataSourceGoogleAppEngineDefaultServiceAccount(),
583584
"google_beyondcorp_app_connection": DataSourceGoogleBeyondcorpAppConnection(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
subcategory: "Alloydb"
3+
description: |-
4+
Fetches the list of supported alloydb database flags in a location.
5+
---
6+
7+
# google\_alloydb\_supported\_database\_flags
8+
9+
Use this data source to get information about the supported alloydb database flags in a location.
10+
11+
## Example Usage
12+
13+
14+
```hcl
15+
data "google_alloydb_supported_database_flags" "qa" {
16+
location = "us-central1"
17+
}
18+
```
19+
20+
## Argument Reference
21+
22+
The following arguments are supported:
23+
24+
* `location` - (required) The canonical id of the location. For example: `us-east1`.
25+
26+
* `project` - (optional) The ID of the project.
27+
28+
## Attributes Reference
29+
30+
In addition to the arguments listed above, the following computed attributes are exported:
31+
32+
* `supported_database_flags` - Contains a list of `flag`, which contains the details about a particular flag.
33+
34+
A `flag` object would contain the following fields:-
35+
36+
* `name` - The name of the flag resource, following Google Cloud conventions, e.g.: * projects/{project}/locations/{location}/flags/{flag} This field currently has no semantic meaning.
37+
38+
* `flag_name` - The name of the database flag, e.g. "max_allowed_packets". The is a possibly key for the Instance.database_flags map field.
39+
40+
* `value_type` - ValueType describes the semantic type of the value that the flag accepts. Regardless of the ValueType, the Instance.database_flags field accepts the stringified version of the value, i.e. "20" or "3.14". The supported values are `VALUE_TYPE_UNSPECIFIED`, `STRING`, `INTEGER`, `FLOAT` and `NONE`.
41+
42+
* `accepts_multiple_values` - Whether the database flag accepts multiple values. If true, a comma-separated list of stringified values may be specified.
43+
44+
* `supported_db_versions` - Major database engine versions for which this flag is supported. The supported values are `POSTGRES_14` and `DATABASE_VERSION_UNSPECIFIED`.
45+
46+
* `requires_db_restart` - Whether setting or updating this flag on an Instance requires a database restart. If a flag that requires database restart is set, the backend will automatically restart the database (making sure to satisfy any availability SLO's).
47+
48+
* `string_restrictions` - Restriction on `STRING` type value. The list of allowed values, if bounded. This field will be empty if there is a unbounded number of allowed values.
49+
50+
* `integer_restrictions` - Restriction on `INTEGER` type value. Specifies the minimum value and the maximum value that can be specified, if applicable.
51+
52+
-> **Note** `string_restrictions` and `integer_restrictions` are part of the union field `restrictions`. The restrictions on the flag value per type. `restrictions` can be either `string_restrictions` or `integer_restrictions` but not both.

0 commit comments

Comments
 (0)