terraform-provider-google/google/transport.go
The Magician 12a25f053b [terraform-conversions] Use placeholder value when generating asset.name from fields empty va… (#3339)
<!-- This change is generated by MagicModules. -->
/cc @nstogner
2019-03-28 14:32:14 -07:00

176 lines
4.0 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) {
re := regexp.MustCompile("{{([[:word:]]+)}}")
f, err := buildReplacementFunc(re, d, config, linkTmpl)
if err != nil {
return "", err
}
return re.ReplaceAllStringFunc(linkTmpl, f), nil
}
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
}
v, ok := d.GetOk(m)
if ok {
return fmt.Sprintf("%v", v)
}
return ""
}
return f, nil
}