blob: 2d8476eac5b98140e6a74f6de0262e1fdc23bc83 [file] [log] [blame]
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package fwresource
import (
"fmt"
"reflect"
"regexp"
"strings"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/hashicorp/terraform-provider-google-beta/google-beta/fwtransport"
"github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource"
)
// GetProject reads the "project" field from the given resource and falls
// back to the provider's value if not given. If the provider's value is not
// given, an error is returned.
func GetProjectFramework(rVal, pVal types.String, diags *diag.Diagnostics) types.String {
return getProjectFromFrameworkSchema("project", rVal, pVal, diags)
}
func getProjectFromFrameworkSchema(projectSchemaField string, rVal, pVal types.String, diags *diag.Diagnostics) types.String {
if !rVal.IsNull() && rVal.ValueString() != "" {
return rVal
}
if !pVal.IsNull() && pVal.ValueString() != "" {
return pVal
}
diags.AddError("required field is not set", fmt.Sprintf("%s is not set", projectSchemaField))
return types.String{}
}
// Parses a project field with the following formats:
// - projects/{my_projects}/{resource_type}/{resource_name}
func ParseProjectFieldValueFramework(resourceType, fieldValue, projectSchemaField string, rVal, pVal types.String, isEmptyValid bool, diags *diag.Diagnostics) *tpgresource.ProjectFieldValue {
if len(fieldValue) == 0 {
if isEmptyValid {
return &tpgresource.ProjectFieldValue{ResourceType: resourceType}
}
diags.AddError("field can not be empty", fmt.Sprintf("The project field for resource %s cannot be empty", resourceType))
return nil
}
r := regexp.MustCompile(fmt.Sprintf(tpgresource.ProjectBasePattern, resourceType))
if parts := r.FindStringSubmatch(fieldValue); parts != nil {
return &tpgresource.ProjectFieldValue{
Project: parts[1],
Name: parts[2],
ResourceType: resourceType,
}
}
project := getProjectFromFrameworkSchema(projectSchemaField, rVal, pVal, diags)
if diags.HasError() {
return nil
}
return &tpgresource.ProjectFieldValue{
Project: project.ValueString(),
Name: tpgresource.GetResourceNameFromSelfLink(fieldValue),
ResourceType: resourceType,
}
}
// This function isn't a test of transport.go; instead, it is used as an alternative
// to ReplaceVars inside tests.
func ReplaceVarsForFrameworkTest(prov *fwtransport.FrameworkProviderConfig, rs *terraform.ResourceState, linkTmpl string) (string, error) {
re := regexp.MustCompile("{{([[:word:]]+)}}")
var project, region, zone string
if strings.Contains(linkTmpl, "{{project}}") {
project = rs.Primary.Attributes["project"]
}
if strings.Contains(linkTmpl, "{{region}}") {
region = tpgresource.GetResourceNameFromSelfLink(rs.Primary.Attributes["region"])
}
if strings.Contains(linkTmpl, "{{zone}}") {
zone = tpgresource.GetResourceNameFromSelfLink(rs.Primary.Attributes["zone"])
}
replaceFunc := func(s string) string {
m := re.FindStringSubmatch(s)[1]
if m == "project" {
return project
}
if m == "region" {
return region
}
if m == "zone" {
return zone
}
if v, ok := rs.Primary.Attributes[m]; ok {
return v
}
// Attempt to draw values from the provider
if f := reflect.Indirect(reflect.ValueOf(prov)).FieldByName(m); f.IsValid() {
return f.String()
}
return ""
}
return re.ReplaceAllStringFunc(linkTmpl, replaceFunc), nil
}