mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-10-01 16:21:06 +00:00
Infers region from zone before using the provider-level region (#938)
This commit is contained in:
parent
9ccbf1f104
commit
da3a6f13a1
@ -27,11 +27,11 @@ func ParseNetworkFieldValue(network string, d TerraformResourceData, config *Con
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ParseSubnetworkFieldValue(subnetwork string, d TerraformResourceData, config *Config) (*RegionalFieldValue, error) {
|
func ParseSubnetworkFieldValue(subnetwork string, d TerraformResourceData, config *Config) (*RegionalFieldValue, error) {
|
||||||
return parseRegionalFieldValue("subnetworks", subnetwork, "project", "region", d, config, true)
|
return parseRegionalFieldValue("subnetworks", subnetwork, "project", "region", "zone", d, config, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseSubnetworkFieldValueWithProjectField(subnetwork, projectField string, d TerraformResourceData, config *Config) (*RegionalFieldValue, error) {
|
func ParseSubnetworkFieldValueWithProjectField(subnetwork, projectField string, d TerraformResourceData, config *Config) (*RegionalFieldValue, error) {
|
||||||
return parseRegionalFieldValue("subnetworks", subnetwork, projectField, "region", d, config, true)
|
return parseRegionalFieldValue("subnetworks", subnetwork, projectField, "region", "zone", d, config, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseSslCertificateFieldValue(sslCertificate string, d TerraformResourceData, config *Config) (*GlobalFieldValue, error) {
|
func ParseSslCertificateFieldValue(sslCertificate string, d TerraformResourceData, config *Config) (*GlobalFieldValue, error) {
|
||||||
@ -260,8 +260,8 @@ func (f RegionalFieldValue) RelativeLink() string {
|
|||||||
// - "" (empty string). RelativeLink() returns empty if isEmptyValid is true.
|
// - "" (empty string). RelativeLink() returns empty if isEmptyValid is true.
|
||||||
//
|
//
|
||||||
// If the project is not specified, it first tries to get the project from the `projectSchemaField` and then fallback on the default project.
|
// If the project is not specified, it first tries to get the project from the `projectSchemaField` and then fallback on the default project.
|
||||||
// If the region is not specified, it first tries to get the region from the `regionSchemaField` and then fallback on the default region.
|
// If the region is not specified, see function documentation for `getRegionFromSchema`.
|
||||||
func parseRegionalFieldValue(resourceType, fieldValue, projectSchemaField, regionSchemaField string, d TerraformResourceData, config *Config, isEmptyValid bool) (*RegionalFieldValue, error) {
|
func parseRegionalFieldValue(resourceType, fieldValue, projectSchemaField, regionSchemaField, zoneSchemaField string, d TerraformResourceData, config *Config, isEmptyValid bool) (*RegionalFieldValue, error) {
|
||||||
if len(fieldValue) == 0 {
|
if len(fieldValue) == 0 {
|
||||||
if isEmptyValid {
|
if isEmptyValid {
|
||||||
return &RegionalFieldValue{resourceType: resourceType}, nil
|
return &RegionalFieldValue{resourceType: resourceType}, nil
|
||||||
@ -294,7 +294,7 @@ func parseRegionalFieldValue(resourceType, fieldValue, projectSchemaField, regio
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
region, err := getRegionFromSchema(regionSchemaField, d, config)
|
region, err := getRegionFromSchema(regionSchemaField, zoneSchemaField, d, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -307,13 +307,24 @@ func parseRegionalFieldValue(resourceType, fieldValue, projectSchemaField, regio
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRegionFromSchema(regionSchemaField string, d TerraformResourceData, config *Config) (string, error) {
|
// Infers the region based on the following (in order of priority):
|
||||||
res, ok := d.GetOk(regionSchemaField)
|
// - `regionSchemaField` in resource schema
|
||||||
if ok && regionSchemaField != "" {
|
// - region extracted from the `zoneSchemaField` in resource schema
|
||||||
return res.(string), nil
|
// - provider-level region
|
||||||
|
// - region extracted from the provider-level zone
|
||||||
|
func getRegionFromSchema(regionSchemaField, zoneSchemaField string, d TerraformResourceData, config *Config) (string, error) {
|
||||||
|
if v, ok := d.GetOk(regionSchemaField); ok && regionSchemaField != "" {
|
||||||
|
return v.(string), nil
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk(zoneSchemaField); ok && zoneSchemaField != "" {
|
||||||
|
return getRegionFromZone(v.(string)), nil
|
||||||
}
|
}
|
||||||
if config.Region != "" {
|
if config.Region != "" {
|
||||||
return config.Region, nil
|
return config.Region, nil
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf("%s: required field is not set", regionSchemaField)
|
if config.Zone != "" {
|
||||||
|
return getRegionFromZone(config.Zone), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("Cannot determine region: set in this resource, or set provider-level 'region' or 'zone'.")
|
||||||
}
|
}
|
||||||
|
@ -239,6 +239,8 @@ func TestParseRegionalFieldValue(t *testing.T) {
|
|||||||
ProjectSchemaValue string
|
ProjectSchemaValue string
|
||||||
RegionSchemaField string
|
RegionSchemaField string
|
||||||
RegionSchemaValue string
|
RegionSchemaValue string
|
||||||
|
ZoneSchemaField string
|
||||||
|
ZoneSchemaValue string
|
||||||
Config *Config
|
Config *Config
|
||||||
}{
|
}{
|
||||||
"subnetwork is a full self link": {
|
"subnetwork is a full self link": {
|
||||||
@ -278,6 +280,23 @@ func TestParseRegionalFieldValue(t *testing.T) {
|
|||||||
Config: &Config{Project: "default-project", Region: "default-region"},
|
Config: &Config{Project: "default-project", Region: "default-region"},
|
||||||
ExpectedRelativeLink: "projects/default-project/regions/us-east1/subnetworks/my-subnetwork",
|
ExpectedRelativeLink: "projects/default-project/regions/us-east1/subnetworks/my-subnetwork",
|
||||||
},
|
},
|
||||||
|
"subnetwork is the name only and region is extracted from the one field.": {
|
||||||
|
FieldValue: "my-subnetwork",
|
||||||
|
ProjectSchemaValue: "schema-project",
|
||||||
|
RegionSchemaField: "region",
|
||||||
|
ZoneSchemaField: "zone",
|
||||||
|
ZoneSchemaValue: "us-central1-a",
|
||||||
|
Config: &Config{Project: "default-project", Region: "default-region"},
|
||||||
|
ExpectedRelativeLink: "projects/default-project/regions/us-central1/subnetworks/my-subnetwork",
|
||||||
|
},
|
||||||
|
"subnetwork is the name only and region is extracted from the provider-level zone.": {
|
||||||
|
FieldValue: "my-subnetwork",
|
||||||
|
ProjectSchemaValue: "schema-project",
|
||||||
|
RegionSchemaField: "region",
|
||||||
|
ZoneSchemaField: "zone",
|
||||||
|
Config: &Config{Project: "default-project", Zone: "us-central1-c"},
|
||||||
|
ExpectedRelativeLink: "projects/default-project/regions/us-central1/subnetworks/my-subnetwork",
|
||||||
|
},
|
||||||
"subnetwork is the name only and no region field is specified": {
|
"subnetwork is the name only and no region field is specified": {
|
||||||
FieldValue: "my-subnetwork",
|
FieldValue: "my-subnetwork",
|
||||||
Config: &Config{Project: "default-project", Region: "default-region"},
|
Config: &Config{Project: "default-project", Region: "default-region"},
|
||||||
@ -305,19 +324,22 @@ func TestParseRegionalFieldValue(t *testing.T) {
|
|||||||
t.Run(tn, func(t *testing.T) {
|
t.Run(tn, func(t *testing.T) {
|
||||||
fieldsInSchema := make(map[string]interface{})
|
fieldsInSchema := make(map[string]interface{})
|
||||||
|
|
||||||
if len(tc.ProjectSchemaValue) > 0 && len(tc.ProjectSchemaField) > 0 {
|
if tc.ProjectSchemaValue != "" && tc.ProjectSchemaField != "" {
|
||||||
fieldsInSchema[tc.ProjectSchemaField] = tc.ProjectSchemaValue
|
fieldsInSchema[tc.ProjectSchemaField] = tc.ProjectSchemaValue
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(tc.RegionSchemaValue) > 0 && len(tc.RegionSchemaField) > 0 {
|
if tc.RegionSchemaValue != "" && tc.RegionSchemaField != "" {
|
||||||
fieldsInSchema[tc.RegionSchemaField] = tc.RegionSchemaValue
|
fieldsInSchema[tc.RegionSchemaField] = tc.RegionSchemaValue
|
||||||
}
|
}
|
||||||
|
if tc.ZoneSchemaValue != "" && tc.ZoneSchemaField != "" {
|
||||||
|
fieldsInSchema[tc.ZoneSchemaField] = tc.ZoneSchemaValue
|
||||||
|
}
|
||||||
|
|
||||||
d := &ResourceDataMock{
|
d := &ResourceDataMock{
|
||||||
FieldsInSchema: fieldsInSchema,
|
FieldsInSchema: fieldsInSchema,
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err := parseRegionalFieldValue(resourceType, tc.FieldValue, tc.ProjectSchemaField, tc.RegionSchemaField, d, tc.Config, tc.IsEmptyValid)
|
v, err := parseRegionalFieldValue(resourceType, tc.FieldValue, tc.ProjectSchemaField, tc.RegionSchemaField, tc.ZoneSchemaField, d, tc.Config, tc.IsEmptyValid)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !tc.ExpectedError {
|
if !tc.ExpectedError {
|
||||||
|
@ -26,23 +26,13 @@ func getRegionFromZone(zone string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRegion reads the "region" field from the given resource data and falls
|
// Infers the region based on the following (in order of priority):
|
||||||
// back to the provider's value if not given. If the provider's value is not
|
// - `region` field in resource schema
|
||||||
// given, checks for "zone" in either the given resource data or provider,
|
// - region extracted from the `zone` field in resource schema
|
||||||
// and extracts region from zone. If "zone" is not provided, returns an
|
// - provider-level region
|
||||||
// error.
|
// - region extracted from the provider-level zone
|
||||||
func getRegion(d *schema.ResourceData, config *Config) (string, error) {
|
func getRegion(d *schema.ResourceData, config *Config) (string, error) {
|
||||||
res, ok := d.GetOk("region")
|
return getRegionFromSchema("region", "zone", d, config)
|
||||||
if !ok {
|
|
||||||
if config.Region != "" {
|
|
||||||
return config.Region, nil
|
|
||||||
}
|
|
||||||
if zone, err := getZone(d, config); err == nil && getRegionFromZone(zone) != "" {
|
|
||||||
return getRegionFromZone(zone), nil
|
|
||||||
}
|
|
||||||
return "", fmt.Errorf("Cannot determine region: set in this resource, or set provider-level 'region' or 'zone'.")
|
|
||||||
}
|
|
||||||
return res.(string), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getZone reads the "zone" value from the given resource data and falls back
|
// getZone reads the "zone" value from the given resource data and falls back
|
||||||
|
Loading…
Reference in New Issue
Block a user