mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-10-07 03:01:06 +00:00
966229afbe
Signed-off-by: Modular Magician <magic-modules@google.com>
187 lines
4.5 KiB
Go
187 lines
4.5 KiB
Go
package google
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"reflect"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"google.golang.org/api/googleapi"
|
|
)
|
|
|
|
var DefaultRequestTimeout = 5 * time.Minute
|
|
|
|
func isEmptyValue(v reflect.Value) bool {
|
|
switch v.Kind() {
|
|
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
|
return v.Len() == 0
|
|
case reflect.Bool:
|
|
return !v.Bool()
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
return v.Int() == 0
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
return v.Uint() == 0
|
|
case reflect.Float32, reflect.Float64:
|
|
return v.Float() == 0
|
|
case reflect.Interface, reflect.Ptr:
|
|
return v.IsNil()
|
|
}
|
|
return false
|
|
}
|
|
|
|
func sendRequest(config *Config, method, rawurl string, body map[string]interface{}) (map[string]interface{}, error) {
|
|
return sendRequestWithTimeout(config, method, rawurl, body, DefaultRequestTimeout)
|
|
}
|
|
|
|
func sendRequestWithTimeout(config *Config, method, rawurl string, body map[string]interface{}, timeout time.Duration) (map[string]interface{}, error) {
|
|
reqHeaders := make(http.Header)
|
|
reqHeaders.Set("User-Agent", config.userAgent)
|
|
reqHeaders.Set("Content-Type", "application/json")
|
|
|
|
if timeout == 0 {
|
|
timeout = time.Duration(1) * time.Hour
|
|
}
|
|
|
|
var res *http.Response
|
|
err := retryTimeDuration(
|
|
func() error {
|
|
var buf bytes.Buffer
|
|
if body != nil {
|
|
err := json.NewEncoder(&buf).Encode(body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
u, err := addQueryParams(rawurl, map[string]string{"alt": "json"})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req, err := http.NewRequest(method, u, &buf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
req.Header = reqHeaders
|
|
res, err = config.client.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := googleapi.CheckResponse(res); err != nil {
|
|
googleapi.CloseBody(res)
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
},
|
|
timeout,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if res == nil {
|
|
return nil, fmt.Errorf("Unable to parse server response. This is most likely a terraform problem, please file a bug at https://github.com/terraform-providers/terraform-provider-google/issues.")
|
|
}
|
|
|
|
// The defer call must be made outside of the retryFunc otherwise it's closed too soon.
|
|
defer googleapi.CloseBody(res)
|
|
|
|
// 204 responses will have no body, so we're going to error with "EOF" if we
|
|
// try to parse it. Instead, we can just return nil.
|
|
if res.StatusCode == 204 {
|
|
return nil, nil
|
|
}
|
|
result := make(map[string]interface{})
|
|
if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func addQueryParams(rawurl string, params map[string]string) (string, error) {
|
|
u, err := url.Parse(rawurl)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
q := u.Query()
|
|
for k, v := range params {
|
|
q.Set(k, v)
|
|
}
|
|
u.RawQuery = q.Encode()
|
|
return u.String(), nil
|
|
}
|
|
|
|
func replaceVars(d TerraformResourceData, config *Config, linkTmpl string) (string, error) {
|
|
// https://github.com/google/re2/wiki/Syntax
|
|
re := regexp.MustCompile("{{([%[:word:]]+)}}")
|
|
f, err := buildReplacementFunc(re, d, config, linkTmpl)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return re.ReplaceAllStringFunc(linkTmpl, f), nil
|
|
}
|
|
|
|
// This function replaces references to Terraform properties (in the form of {{var}}) with their value in Terraform
|
|
// It also replaces {{project}}, {{region}}, and {{zone}} with their appropriate values
|
|
// This function supports URL-encoding the result by prepending '%' to the field name e.g. {{%var}}
|
|
func buildReplacementFunc(re *regexp.Regexp, d TerraformResourceData, config *Config, linkTmpl string) (func(string) string, error) {
|
|
var project, region, zone string
|
|
var err error
|
|
|
|
if strings.Contains(linkTmpl, "{{project}}") {
|
|
project, err = getProject(d, config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
if strings.Contains(linkTmpl, "{{region}}") {
|
|
region, err = getRegion(d, config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
if strings.Contains(linkTmpl, "{{zone}}") {
|
|
zone, err = getZone(d, config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
f := 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 string(m[0]) == "%" {
|
|
v, ok := d.GetOkExists(m[1:])
|
|
if ok {
|
|
return url.PathEscape(fmt.Sprintf("%v", v))
|
|
}
|
|
} else {
|
|
v, ok := d.GetOkExists(m)
|
|
if ok {
|
|
return fmt.Sprintf("%v", v)
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
return f, nil
|
|
}
|