package openstack import ( "fmt" "net/http" "sort" "strings" "github.com/Unknwon/com" "github.com/gophercloud/gophercloud" "github.com/hashicorp/terraform/helper/schema" ) // BuildRequest takes an opts struct and builds a request body for // Gophercloud to execute func BuildRequest(opts interface{}, parent string) (map[string]interface{}, error) { b, err := gophercloud.BuildRequestBody(opts, "") if err != nil { return nil, err } b = AddValueSpecs(b) return map[string]interface{}{parent: b}, nil } // CheckDeleted checks the error to see if it's a 404 (Not Found) and, if so, // sets the resource ID to the empty string instead of throwing an error. func CheckDeleted(d *schema.ResourceData, err error, msg string) error { if _, ok := err.(gophercloud.ErrDefault404); ok { d.SetId("") return nil } return fmt.Errorf("%s: %s", msg, err) } // GetRegion returns the region that was specified in the resource. If a // region was not set, the provider-level region is checked. The provider-level // region can either be set by the region argument or by OS_REGION_NAME. func GetRegion(d *schema.ResourceData, config *Config) string { if v, ok := d.GetOk("region"); ok { return v.(string) } return config.Region } // AddValueSpecs expands the 'value_specs' object and removes 'value_specs' // from the reqeust body. func AddValueSpecs(body map[string]interface{}) map[string]interface{} { if body["value_specs"] != nil { for k, v := range body["value_specs"].(map[string]interface{}) { body[k] = v } delete(body, "value_specs") } return body } // MapValueSpecs converts ResourceData into a map func MapValueSpecs(d *schema.ResourceData) map[string]string { m := make(map[string]string) for key, val := range d.Get("value_specs").(map[string]interface{}) { m[key] = val.(string) } return m } // List of headers that need to be redacted var REDACT_HEADERS = []string{"x-auth-token", "x-auth-key", "x-service-token", "x-storage-token", "x-account-meta-temp-url-key", "x-account-meta-temp-url-key-2", "x-container-meta-temp-url-key", "x-container-meta-temp-url-key-2", "set-cookie", "x-subject-token"} // RedactHeaders processes a headers object, returning a redacted list func RedactHeaders(headers http.Header) (processedHeaders []string) { for name, header := range headers { for _, v := range header { if com.IsSliceContainsStr(REDACT_HEADERS, name) { processedHeaders = append(processedHeaders, fmt.Sprintf("%v: %v", name, "***")) } else { processedHeaders = append(processedHeaders, fmt.Sprintf("%v: %v", name, v)) } } } return } // FormatHeaders processes a headers object plus a deliminator, returning a string func FormatHeaders(headers http.Header, seperator string) string { redactedHeaders := RedactHeaders(headers) sort.Strings(redactedHeaders) return strings.Join(redactedHeaders, seperator) }