diff --git a/google/provider_compute_gen.go b/google/provider_compute_gen.go index 170e19530c9..42a3563e078 100644 --- a/google/provider_compute_gen.go +++ b/google/provider_compute_gen.go @@ -40,5 +40,6 @@ var GeneratedComputeResourcesMap = map[string]*schema.Resource{ "google_compute_target_ssl_proxy": resourceComputeTargetSslProxy(), "google_compute_target_tcp_proxy": resourceComputeTargetTcpProxy(), "google_compute_vpn_gateway": resourceComputeVpnGateway(), + "google_compute_url_map": resourceComputeUrlMap(), "google_compute_vpn_tunnel": resourceComputeVpnTunnel(), } diff --git a/google/resource_compute_address.go b/google/resource_compute_address.go index 87808f2b17b..aee67966c11 100644 --- a/google/resource_compute_address.go +++ b/google/resource_compute_address.go @@ -174,6 +174,12 @@ func resourceComputeAddressCreate(d *schema.ResourceData, meta interface{}) erro } else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) { obj["labels"] = labelsProp } + labelFingerprintProp, err := expandComputeAddressLabelFingerprint(d.Get("label_fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("label_fingerprint"); !isEmptyValue(reflect.ValueOf(labelFingerprintProp)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) { + obj["labelFingerprint"] = labelFingerprintProp + } regionProp, err := expandComputeAddressRegion(d.Get("region"), d, config) if err != nil { return err @@ -335,8 +341,12 @@ func resourceComputeAddressUpdate(d *schema.ResourceData, meta interface{}) erro } else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { obj["labels"] = labelsProp } - labelFingerprintProp := d.Get("label_fingerprint") - obj["labelFingerprint"] = labelFingerprintProp + labelFingerprintProp, err := expandComputeAddressLabelFingerprint(d.Get("label_fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("label_fingerprint"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) { + obj["labelFingerprint"] = labelFingerprintProp + } url, err := replaceVars(d, config, "https://www.googleapis.com/compute/beta/projects/{{project}}/regions/{{region}}/addresses/{{name}}/setLabels") if err != nil { @@ -517,6 +527,10 @@ func expandComputeAddressLabels(v interface{}, d *schema.ResourceData, config *C return m, nil } +func expandComputeAddressLabelFingerprint(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + func expandComputeAddressRegion(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { f, err := parseGlobalFieldValue("regions", v.(string), "project", d, config, true) if err != nil { diff --git a/google/resource_compute_disk.go b/google/resource_compute_disk.go index fe89731f348..782881be203 100644 --- a/google/resource_compute_disk.go +++ b/google/resource_compute_disk.go @@ -405,6 +405,12 @@ func resourceComputeDiskCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) obj := make(map[string]interface{}) + labelFingerprintProp, err := expandComputeDiskLabelFingerprint(d.Get("label_fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("label_fingerprint"); !isEmptyValue(reflect.ValueOf(labelFingerprintProp)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) { + obj["labelFingerprint"] = labelFingerprintProp + } descriptionProp, err := expandComputeDiskDescription(d.Get("description"), d, config) if err != nil { return err @@ -613,8 +619,12 @@ func resourceComputeDiskUpdate(d *schema.ResourceData, meta interface{}) error { if d.HasChange("label_fingerprint") || d.HasChange("labels") { obj := make(map[string]interface{}) - labelFingerprintProp := d.Get("label_fingerprint") - obj["labelFingerprint"] = labelFingerprintProp + labelFingerprintProp, err := expandComputeDiskLabelFingerprint(d.Get("label_fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("label_fingerprint"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) { + obj["labelFingerprint"] = labelFingerprintProp + } labelsProp, err := expandComputeDiskLabels(d.Get("labels"), d, config) if err != nil { return err @@ -960,6 +970,10 @@ func flattenComputeDiskSourceSnapshotId(v interface{}) interface{} { return v } +func expandComputeDiskLabelFingerprint(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + func expandComputeDiskDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { return v, nil } diff --git a/google/resource_compute_forwarding_rule.go b/google/resource_compute_forwarding_rule.go index 0d199fc58af..b45839edeee 100644 --- a/google/resource_compute_forwarding_rule.go +++ b/google/resource_compute_forwarding_rule.go @@ -162,7 +162,7 @@ See https://terraform.io/docs/providers/google/provider_versions.html for more d Computed: true, Deprecated: `This field is in beta and will be removed from this provider. Use the terraform-provider-google-beta provider to continue using it. -See https://terraform.io/docs/provider/google/provider_versions.html for more details on beta fields.`, +See https://terraform.io/docs/providers/google/provider_versions.html for more details on beta fields.`, }, "service_name": { Type: schema.TypeString, @@ -267,6 +267,12 @@ func resourceComputeForwardingRuleCreate(d *schema.ResourceData, meta interface{ } else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) { obj["labels"] = labelsProp } + labelFingerprintProp, err := expandComputeForwardingRuleLabelFingerprint(d.Get("label_fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("label_fingerprint"); !isEmptyValue(reflect.ValueOf(labelFingerprintProp)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) { + obj["labelFingerprint"] = labelFingerprintProp + } networkTierProp, err := expandComputeForwardingRuleNetworkTier(d.Get("network_tier"), d, config) if err != nil { return err @@ -502,8 +508,12 @@ func resourceComputeForwardingRuleUpdate(d *schema.ResourceData, meta interface{ } else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { obj["labels"] = labelsProp } - labelFingerprintProp := d.Get("label_fingerprint") - obj["labelFingerprint"] = labelFingerprintProp + labelFingerprintProp, err := expandComputeForwardingRuleLabelFingerprint(d.Get("label_fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("label_fingerprint"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) { + obj["labelFingerprint"] = labelFingerprintProp + } url, err := replaceVars(d, config, "https://www.googleapis.com/compute/beta/projects/{{project}}/regions/{{region}}/forwardingRules/{{name}}/setLabels") if err != nil { @@ -803,6 +813,10 @@ func expandComputeForwardingRuleLabels(v interface{}, d *schema.ResourceData, co return m, nil } +func expandComputeForwardingRuleLabelFingerprint(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + func expandComputeForwardingRuleNetworkTier(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { return v, nil } diff --git a/google/resource_compute_global_address.go b/google/resource_compute_global_address.go index 74b3bd1b171..7a1ae672f36 100644 --- a/google/resource_compute_global_address.go +++ b/google/resource_compute_global_address.go @@ -116,7 +116,7 @@ See https://terraform.io/docs/providers/google/provider_versions.html for more d Computed: true, Deprecated: `This field is in beta and will be removed from this provider. Use the terraform-provider-google-beta provider to continue using it. -See https://terraform.io/docs/provider/google/provider_versions.html for more details on beta fields.`, +See https://terraform.io/docs/providers/google/provider_versions.html for more details on beta fields.`, }, "project": { Type: schema.TypeString, @@ -154,6 +154,12 @@ func resourceComputeGlobalAddressCreate(d *schema.ResourceData, meta interface{} } else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) { obj["labels"] = labelsProp } + labelFingerprintProp, err := expandComputeGlobalAddressLabelFingerprint(d.Get("label_fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("label_fingerprint"); !isEmptyValue(reflect.ValueOf(labelFingerprintProp)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) { + obj["labelFingerprint"] = labelFingerprintProp + } ipVersionProp, err := expandComputeGlobalAddressIpVersion(d.Get("ip_version"), d, config) if err != nil { return err @@ -339,8 +345,12 @@ func resourceComputeGlobalAddressUpdate(d *schema.ResourceData, meta interface{} } else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { obj["labels"] = labelsProp } - labelFingerprintProp := d.Get("label_fingerprint") - obj["labelFingerprint"] = labelFingerprintProp + labelFingerprintProp, err := expandComputeGlobalAddressLabelFingerprint(d.Get("label_fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("label_fingerprint"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) { + obj["labelFingerprint"] = labelFingerprintProp + } url, err := replaceVars(d, config, "https://www.googleapis.com/compute/beta/projects/{{project}}/global/addresses/{{name}}/setLabels") if err != nil { @@ -501,6 +511,10 @@ func expandComputeGlobalAddressLabels(v interface{}, d *schema.ResourceData, con return m, nil } +func expandComputeGlobalAddressLabelFingerprint(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + func expandComputeGlobalAddressIpVersion(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { return v, nil } diff --git a/google/resource_compute_region_disk.go b/google/resource_compute_region_disk.go index d05f7bddacf..5a91dabac99 100644 --- a/google/resource_compute_region_disk.go +++ b/google/resource_compute_region_disk.go @@ -183,6 +183,12 @@ func resourceComputeRegionDiskCreate(d *schema.ResourceData, meta interface{}) e config := meta.(*Config) obj := make(map[string]interface{}) + labelFingerprintProp, err := expandComputeRegionDiskLabelFingerprint(d.Get("label_fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("label_fingerprint"); !isEmptyValue(reflect.ValueOf(labelFingerprintProp)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) { + obj["labelFingerprint"] = labelFingerprintProp + } descriptionProp, err := expandComputeRegionDiskDescription(d.Get("description"), d, config) if err != nil { return err @@ -379,8 +385,12 @@ func resourceComputeRegionDiskUpdate(d *schema.ResourceData, meta interface{}) e if d.HasChange("label_fingerprint") || d.HasChange("labels") { obj := make(map[string]interface{}) - labelFingerprintProp := d.Get("label_fingerprint") - obj["labelFingerprint"] = labelFingerprintProp + labelFingerprintProp, err := expandComputeRegionDiskLabelFingerprint(d.Get("label_fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("label_fingerprint"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) { + obj["labelFingerprint"] = labelFingerprintProp + } labelsProp, err := expandComputeRegionDiskLabels(d.Get("labels"), d, config) if err != nil { return err @@ -679,6 +689,10 @@ func flattenComputeRegionDiskSourceSnapshotId(v interface{}) interface{} { return v } +func expandComputeRegionDiskLabelFingerprint(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + func expandComputeRegionDiskDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { return v, nil } diff --git a/google/resource_compute_subnetwork.go b/google/resource_compute_subnetwork.go index 79d83980819..ba76d27ca89 100644 --- a/google/resource_compute_subnetwork.go +++ b/google/resource_compute_subnetwork.go @@ -234,6 +234,12 @@ func resourceComputeSubnetworkCreate(d *schema.ResourceData, meta interface{}) e } else if v, ok := d.GetOkExists("enable_flow_logs"); ok || !reflect.DeepEqual(v, enableFlowLogsProp) { obj["enableFlowLogs"] = enableFlowLogsProp } + fingerprintProp, err := expandComputeSubnetworkFingerprint(d.Get("fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("fingerprint"); !isEmptyValue(reflect.ValueOf(fingerprintProp)) && (ok || !reflect.DeepEqual(v, fingerprintProp)) { + obj["fingerprint"] = fingerprintProp + } secondaryIpRangesProp, err := expandComputeSubnetworkSecondaryIpRange(d.Get("secondary_ip_range"), d, config) if err != nil { return err @@ -407,8 +413,12 @@ func resourceComputeSubnetworkUpdate(d *schema.ResourceData, meta interface{}) e } else if v, ok := d.GetOkExists("enable_flow_logs"); ok || !reflect.DeepEqual(v, enableFlowLogsProp) { obj["enableFlowLogs"] = enableFlowLogsProp } - fingerprintProp := d.Get("fingerprint") - obj["fingerprint"] = fingerprintProp + fingerprintProp, err := expandComputeSubnetworkFingerprint(d.Get("fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("fingerprint"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, fingerprintProp)) { + obj["fingerprint"] = fingerprintProp + } secondaryIpRangesProp, err := expandComputeSubnetworkSecondaryIpRange(d.Get("secondary_ip_range"), d, config) if err != nil { return err @@ -635,6 +645,10 @@ func expandComputeSubnetworkEnableFlowLogs(v interface{}, d *schema.ResourceData return v, nil } +func expandComputeSubnetworkFingerprint(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + func expandComputeSubnetworkSecondaryIpRange(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) req := make([]interface{}, 0, len(l)) diff --git a/google/resource_compute_url_map.go b/google/resource_compute_url_map.go index b807cb7f868..9ed19dffc4b 100644 --- a/google/resource_compute_url_map.go +++ b/google/resource_compute_url_map.go @@ -1,11 +1,28 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + package google import ( "fmt" + "log" + "reflect" "strconv" + "time" "github.com/hashicorp/terraform/helper/schema" - "google.golang.org/api/compute/v1" + compute "google.golang.org/api/compute/v1" ) func resourceComputeUrlMap() *schema.Resource { @@ -16,96 +33,88 @@ func resourceComputeUrlMap() *schema.Resource { Delete: resourceComputeUrlMapDelete, Importer: &schema.ResourceImporter{ - State: resourceComputeUrlMapImportState, + State: resourceComputeUrlMapImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(240 * time.Second), + Update: schema.DefaultTimeout(240 * time.Second), + Delete: schema.DefaultTimeout(240 * time.Second), }, Schema: map[string]*schema.Schema{ - "default_service": &schema.Schema{ - Type: schema.TypeString, - Required: true, + "default_service": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, }, - - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, ForceNew: true, }, - - "description": &schema.Schema{ + "description": { Type: schema.TypeString, Optional: true, }, - - "fingerprint": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - }, - - "host_rule": &schema.Schema{ + "host_rule": { Type: schema.TypeSet, Optional: true, - // TODO(evandbrown): Enable when lists support validation - //ValidateFunc: validateHostRules, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "description": &schema.Schema{ - Type: schema.TypeString, - Optional: true, - }, - - "hosts": &schema.Schema{ + "hosts": { Type: schema.TypeList, Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, - - "path_matcher": &schema.Schema{ + "path_matcher": { Type: schema.TypeString, Required: true, }, + "description": { + Type: schema.TypeString, + Optional: true, + }, }, }, + // Default schema.HashSchema is used. }, - - "map_id": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - }, - - "path_matcher": &schema.Schema{ + "path_matcher": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "default_service": &schema.Schema{ + "default_service": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + }, + "name": { Type: schema.TypeString, Required: true, }, - - "description": &schema.Schema{ + "description": { Type: schema.TypeString, Optional: true, }, - - "name": &schema.Schema{ - Type: schema.TypeString, - Required: true, - }, - - "path_rule": &schema.Schema{ + "path_rule": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "paths": &schema.Schema{ - Type: schema.TypeList, - Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, + "service": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, }, - - "service": &schema.Schema{ - Type: schema.TypeString, - Required: true, + "paths": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, }, }, @@ -113,577 +122,707 @@ func resourceComputeUrlMap() *schema.Resource { }, }, }, - - "project": &schema.Schema{ - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: true, - }, - - "self_link": &schema.Schema{ - Type: schema.TypeString, - Computed: true, - }, - - "test": &schema.Schema{ + "test": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "description": &schema.Schema{ - Type: schema.TypeString, - Optional: true, - }, - - "host": &schema.Schema{ + "host": { Type: schema.TypeString, Required: true, }, - - "path": &schema.Schema{ + "path": { Type: schema.TypeString, Required: true, }, - - "service": &schema.Schema{ + "service": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + }, + "description": { Type: schema.TypeString, - Required: true, + Optional: true, }, }, }, }, + "creation_timestamp": { + Type: schema.TypeString, + Computed: true, + }, + "fingerprint": { + Type: schema.TypeString, + Computed: true, + }, + "map_id": { + Type: schema.TypeInt, + Computed: true, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + "self_link": { + Type: schema.TypeString, + Computed: true, + }, }, } } -func createHostRule(v interface{}) *compute.HostRule { - _hostRule := v.(map[string]interface{}) - - _hosts := _hostRule["hosts"].([]interface{}) - hosts := make([]string, len(_hosts)) +func resourceComputeUrlMapCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) - for i, v := range _hosts { - hosts[i] = v.(string) + obj := make(map[string]interface{}) + defaultServiceProp, err := expandComputeUrlMapDefaultService(d.Get("default_service"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("default_service"); !isEmptyValue(reflect.ValueOf(defaultServiceProp)) && (ok || !reflect.DeepEqual(v, defaultServiceProp)) { + obj["defaultService"] = defaultServiceProp } - - pathMatcher := _hostRule["path_matcher"].(string) - - hostRule := &compute.HostRule{ - Hosts: hosts, - PathMatcher: pathMatcher, + descriptionProp, err := expandComputeUrlMapDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp } - - if v, ok := _hostRule["description"]; ok { - hostRule.Description = v.(string) + hostRulesProp, err := expandComputeUrlMapHost_rule(d.Get("host_rule"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("host_rule"); !isEmptyValue(reflect.ValueOf(hostRulesProp)) && (ok || !reflect.DeepEqual(v, hostRulesProp)) { + obj["hostRules"] = hostRulesProp + } + fingerprintProp, err := expandComputeUrlMapFingerprint(d.Get("fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("fingerprint"); !isEmptyValue(reflect.ValueOf(fingerprintProp)) && (ok || !reflect.DeepEqual(v, fingerprintProp)) { + obj["fingerprint"] = fingerprintProp + } + nameProp, err := expandComputeUrlMapName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + pathMatchersProp, err := expandComputeUrlMapPath_matcher(d.Get("path_matcher"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("path_matcher"); !isEmptyValue(reflect.ValueOf(pathMatchersProp)) && (ok || !reflect.DeepEqual(v, pathMatchersProp)) { + obj["pathMatchers"] = pathMatchersProp + } + testsProp, err := expandComputeUrlMapTest(d.Get("test"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("test"); !isEmptyValue(reflect.ValueOf(testsProp)) && (ok || !reflect.DeepEqual(v, testsProp)) { + obj["tests"] = testsProp } - return hostRule -} - -func createPathMatcher(v interface{}) *compute.PathMatcher { - _pathMatcher := v.(map[string]interface{}) - - _pathRules := _pathMatcher["path_rule"].([]interface{}) - pathRules := make([]*compute.PathRule, len(_pathRules)) - - for ip, vp := range _pathRules { - _pathRule := vp.(map[string]interface{}) - - _paths := _pathRule["paths"].([]interface{}) - paths := make([]string, len(_paths)) - - for ipp, vpp := range _paths { - paths[ipp] = vpp.(string) - } + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/urlMaps") + if err != nil { + return err + } - service := _pathRule["service"].(string) + log.Printf("[DEBUG] Creating new UrlMap: %#v", obj) + res, err := sendRequest(config, "POST", url, obj) + if err != nil { + return fmt.Errorf("Error creating UrlMap: %s", err) + } - pathRule := &compute.PathRule{ - Paths: paths, - Service: service, - } + // Store the ID now + id, err := replaceVars(d, config, "{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) - pathRules[ip] = pathRule + project, err := getProject(d, config) + if err != nil { + return err + } + op := &compute.Operation{} + err = Convert(res, op) + if err != nil { + return err } - name := _pathMatcher["name"].(string) - defaultService := _pathMatcher["default_service"].(string) + waitErr := computeOperationWaitTime( + config.clientCompute, op, project, "Creating UrlMap", + int(d.Timeout(schema.TimeoutCreate).Minutes())) - pathMatcher := &compute.PathMatcher{ - PathRules: pathRules, - Name: name, - DefaultService: defaultService, + if waitErr != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create UrlMap: %s", waitErr) } - if vp, okp := _pathMatcher["description"]; okp { - pathMatcher.Description = vp.(string) - } + log.Printf("[DEBUG] Finished creating UrlMap %q: %#v", d.Id(), res) - return pathMatcher + return resourceComputeUrlMapRead(d, meta) } -func createUrlMapTest(v interface{}) *compute.UrlMapTest { - _test := v.(map[string]interface{}) +func resourceComputeUrlMapRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) - host := _test["host"].(string) - path := _test["path"].(string) - service := _test["service"].(string) + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/urlMaps/{{name}}") + if err != nil { + return err + } - test := &compute.UrlMapTest{ - Host: host, - Path: path, - Service: service, + res, err := sendRequest(config, "GET", url, nil) + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("ComputeUrlMap %q", d.Id())) } - if vp, okp := _test["description"]; okp { - test.Description = vp.(string) + if err := d.Set("creation_timestamp", flattenComputeUrlMapCreationTimestamp(res["creationTimestamp"])); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("default_service", flattenComputeUrlMapDefaultService(res["defaultService"])); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("description", flattenComputeUrlMapDescription(res["description"])); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("host_rule", flattenComputeUrlMapHost_rule(res["hostRules"])); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("map_id", flattenComputeUrlMapMap_id(res["id"])); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("fingerprint", flattenComputeUrlMapFingerprint(res["fingerprint"])); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("name", flattenComputeUrlMapName(res["name"])); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("path_matcher", flattenComputeUrlMapPath_matcher(res["pathMatchers"])); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("test", flattenComputeUrlMapTest(res["tests"])); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + if err := d.Set("self_link", ConvertSelfLinkToV1(res["selfLink"].(string))); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) + } + project, err := getProject(d, config) + if err != nil { + return err + } + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading UrlMap: %s", err) } - return test + return nil } -func resourceComputeUrlMapCreate(d *schema.ResourceData, meta interface{}) error { +func resourceComputeUrlMapUpdate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) - project, err := getProject(d, config) + obj := make(map[string]interface{}) + defaultServiceProp, err := expandComputeUrlMapDefaultService(d.Get("default_service"), d, config) if err != nil { return err + } else if v, ok := d.GetOkExists("default_service"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, defaultServiceProp)) { + obj["defaultService"] = defaultServiceProp } - - name := d.Get("name").(string) - defaultService := d.Get("default_service").(string) - - urlMap := &compute.UrlMap{ - Name: name, - DefaultService: defaultService, + descriptionProp, err := expandComputeUrlMapDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp } - - if v, ok := d.GetOk("description"); ok { - urlMap.Description = v.(string) + hostRulesProp, err := expandComputeUrlMapHost_rule(d.Get("host_rule"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("host_rule"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, hostRulesProp)) { + obj["hostRules"] = hostRulesProp } - - _hostRules := d.Get("host_rule").(*schema.Set) - urlMap.HostRules = make([]*compute.HostRule, _hostRules.Len()) - - for i, v := range _hostRules.List() { - urlMap.HostRules[i] = createHostRule(v) + fingerprintProp, err := expandComputeUrlMapFingerprint(d.Get("fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("fingerprint"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, fingerprintProp)) { + obj["fingerprint"] = fingerprintProp } - - _pathMatchers := d.Get("path_matcher").([]interface{}) - urlMap.PathMatchers = make([]*compute.PathMatcher, len(_pathMatchers)) - - for i, v := range _pathMatchers { - urlMap.PathMatchers[i] = createPathMatcher(v) + nameProp, err := expandComputeUrlMapName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp } - - _tests := make([]interface{}, 0) - if v, ok := d.GetOk("test"); ok { - _tests = v.([]interface{}) + pathMatchersProp, err := expandComputeUrlMapPath_matcher(d.Get("path_matcher"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("path_matcher"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, pathMatchersProp)) { + obj["pathMatchers"] = pathMatchersProp + } + testsProp, err := expandComputeUrlMapTest(d.Get("test"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("test"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, testsProp)) { + obj["tests"] = testsProp } - urlMap.Tests = make([]*compute.UrlMapTest, len(_tests)) - for i, v := range _tests { - urlMap.Tests[i] = createUrlMapTest(v) + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/urlMaps/{{name}}") + if err != nil { + return err } - op, err := config.clientCompute.UrlMaps.Insert(project, urlMap).Do() + log.Printf("[DEBUG] Updating UrlMap %q: %#v", d.Id(), obj) + res, err := sendRequest(config, "PUT", url, obj) if err != nil { - return fmt.Errorf("Error, failed to insert Url Map %s: %s", name, err) + return fmt.Errorf("Error updating UrlMap %q: %s", d.Id(), err) + } + + project, err := getProject(d, config) + if err != nil { + return err + } + op := &compute.Operation{} + err = Convert(res, op) + if err != nil { + return err } - err = computeOperationWait(config.clientCompute, op, project, "Insert Url Map") + err = computeOperationWaitTime( + config.clientCompute, op, project, "Updating UrlMap", + int(d.Timeout(schema.TimeoutUpdate).Minutes())) if err != nil { - return fmt.Errorf("Error, failed waitng to insert Url Map %s: %s", name, err) + return err } return resourceComputeUrlMapRead(d, meta) } -func resourceComputeUrlMapRead(d *schema.ResourceData, meta interface{}) error { +func resourceComputeUrlMapDelete(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) - project, err := getProject(d, config) + url, err := replaceVars(d, config, "https://www.googleapis.com/compute/v1/projects/{{project}}/global/urlMaps/{{name}}") if err != nil { return err } - name := d.Get("name").(string) - - urlMap, err := config.clientCompute.UrlMaps.Get(project, name).Do() + var obj map[string]interface{} + log.Printf("[DEBUG] Deleting UrlMap %q", d.Id()) + res, err := sendRequest(config, "DELETE", url, obj) + if err != nil { + return handleNotFoundError(err, d, "UrlMap") + } + project, err := getProject(d, config) if err != nil { - return handleNotFoundError(err, d, fmt.Sprintf("URL Map %q", d.Get("name").(string))) + return err + } + op := &compute.Operation{} + err = Convert(res, op) + if err != nil { + return err } - d.SetId(name) - d.Set("project", project) - d.Set("self_link", urlMap.SelfLink) - d.Set("map_id", strconv.FormatUint(urlMap.Id, 10)) - d.Set("fingerprint", urlMap.Fingerprint) - d.Set("default_service", urlMap.DefaultService) + err = computeOperationWaitTime( + config.clientCompute, op, project, "Deleting UrlMap", + int(d.Timeout(schema.TimeoutDelete).Minutes())) - hostRuleMap := make(map[string]*compute.HostRule) - for _, v := range urlMap.HostRules { - hostRuleMap[v.PathMatcher] = v + if err != nil { + return err } - /* Only read host rules into our TF state that we have defined */ - _hostRules := d.Get("host_rule").(*schema.Set).List() - _newHostRules := make([]interface{}, 0) - for _, v := range _hostRules { - _hostRule := v.(map[string]interface{}) - _pathMatcher := _hostRule["path_matcher"].(string) + log.Printf("[DEBUG] Finished deleting UrlMap %q: %#v", d.Id(), res) + return nil +} - /* Delete local entries that are no longer found on the GCE server */ - if hostRule, ok := hostRuleMap[_pathMatcher]; ok { - _newHostRule := make(map[string]interface{}) - _newHostRule["path_matcher"] = _pathMatcher +func resourceComputeUrlMapImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + parseImportId([]string{"projects/(?P[^/]+)/global/urlMaps/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)"}, d, config) - hostsSet := make(map[string]bool) - for _, host := range hostRule.Hosts { - hostsSet[host] = true - } + // Replace import id for the resource id + id, err := replaceVars(d, config, "{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) - /* Only store hosts we are keeping track of */ - _newHosts := make([]interface{}, 0) - for _, vp := range _hostRule["hosts"].([]interface{}) { - if _, okp := hostsSet[vp.(string)]; okp { - _newHosts = append(_newHosts, vp) - } - } + return []*schema.ResourceData{d}, nil +} - _newHostRule["hosts"] = _newHosts - _newHostRule["description"] = hostRule.Description +func flattenComputeUrlMapCreationTimestamp(v interface{}) interface{} { + return v +} - _newHostRules = append(_newHostRules, _newHostRule) - } +func flattenComputeUrlMapDefaultService(v interface{}) interface{} { + if v == nil { + return v } + return ConvertSelfLinkToV1(v.(string)) +} - d.Set("host_rule", _newHostRules) - - pathMatcherMap := make(map[string]*compute.PathMatcher) - for _, v := range urlMap.PathMatchers { - pathMatcherMap[v.Name] = v - } +func flattenComputeUrlMapDescription(v interface{}) interface{} { + return v +} - /* Only read path matchers into our TF state that we have defined */ - _pathMatchers := d.Get("path_matcher").([]interface{}) - _newPathMatchers := make([]interface{}, 0) - for _, v := range _pathMatchers { - _pathMatcher := v.(map[string]interface{}) - _name := _pathMatcher["name"].(string) +func flattenComputeUrlMapHost_rule(v interface{}) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + transformed = append(transformed, map[string]interface{}{ + "description": flattenComputeUrlMapHost_ruleDescription(original["description"]), + "hosts": flattenComputeUrlMapHost_ruleHosts(original["hosts"]), + "path_matcher": flattenComputeUrlMapHost_rulePathMatcher(original["pathMatcher"]), + }) + } + return transformed +} +func flattenComputeUrlMapHost_ruleDescription(v interface{}) interface{} { + return v +} - if pathMatcher, ok := pathMatcherMap[_name]; ok { - _newPathMatcher := make(map[string]interface{}) - _newPathMatcher["name"] = _name - _newPathMatcher["default_service"] = pathMatcher.DefaultService - _newPathMatcher["description"] = pathMatcher.Description +func flattenComputeUrlMapHost_ruleHosts(v interface{}) interface{} { + return v +} - _newPathRules := make([]interface{}, len(pathMatcher.PathRules)) - for ip, pathRule := range pathMatcher.PathRules { - _newPathRule := make(map[string]interface{}) - _newPathRule["service"] = pathRule.Service - _paths := make([]interface{}, len(pathRule.Paths)) +func flattenComputeUrlMapHost_rulePathMatcher(v interface{}) interface{} { + return v +} - for ipp, vpp := range pathRule.Paths { - _paths[ipp] = vpp - } +func flattenComputeUrlMapMap_id(v interface{}) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := strconv.ParseInt(strVal, 10, 64); err == nil { + return intVal + } // let terraform core handle it if we can't convert the string to an int. + } + return v +} - _newPathRule["paths"] = _paths +func flattenComputeUrlMapFingerprint(v interface{}) interface{} { + return v +} - _newPathRules[ip] = _newPathRule - } +func flattenComputeUrlMapName(v interface{}) interface{} { + return v +} - _newPathMatcher["path_rule"] = _newPathRules - _newPathMatchers = append(_newPathMatchers, _newPathMatcher) - } +func flattenComputeUrlMapPath_matcher(v interface{}) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + transformed = append(transformed, map[string]interface{}{ + "default_service": flattenComputeUrlMapPath_matcherDefaultService(original["defaultService"]), + "description": flattenComputeUrlMapPath_matcherDescription(original["description"]), + "name": flattenComputeUrlMapPath_matcherName(original["name"]), + "path_rule": flattenComputeUrlMapPath_matcherPath_rule(original["pathRules"]), + }) + } + return transformed +} +func flattenComputeUrlMapPath_matcherDefaultService(v interface{}) interface{} { + if v == nil { + return v } + return ConvertSelfLinkToV1(v.(string)) +} - d.Set("path_matcher", _newPathMatchers) +func flattenComputeUrlMapPath_matcherDescription(v interface{}) interface{} { + return v +} - testMap := make(map[string]*compute.UrlMapTest) - for _, v := range urlMap.Tests { - testMap[fmt.Sprintf("%s/%s", v.Host, v.Path)] = v - } +func flattenComputeUrlMapPath_matcherName(v interface{}) interface{} { + return v +} - _tests := make([]interface{}, 0) - /* Only read tests into our TF state that we have defined */ - if v, ok := d.GetOk("test"); ok { - _tests = v.([]interface{}) +func flattenComputeUrlMapPath_matcherPath_rule(v interface{}) interface{} { + if v == nil { + return v } - _newTests := make([]interface{}, 0) - for _, v := range _tests { - _test := v.(map[string]interface{}) - _host := _test["host"].(string) - _path := _test["path"].(string) - - /* Delete local entries that are no longer found on the GCE server */ - if test, ok := testMap[fmt.Sprintf("%s/%s", _host, _path)]; ok { - _newTest := make(map[string]interface{}) - _newTest["host"] = _host - _newTest["path"] = _path - _newTest["description"] = test.Description - _newTest["service"] = test.Service - - _newTests = append(_newTests, _newTest) - } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + transformed = append(transformed, map[string]interface{}{ + "paths": flattenComputeUrlMapPath_matcherPath_rulePaths(original["paths"]), + "service": flattenComputeUrlMapPath_matcherPath_ruleService(original["service"]), + }) } + return transformed +} +func flattenComputeUrlMapPath_matcherPath_rulePaths(v interface{}) interface{} { + return v +} - d.Set("test", _newTests) +func flattenComputeUrlMapPath_matcherPath_ruleService(v interface{}) interface{} { + if v == nil { + return v + } + return ConvertSelfLinkToV1(v.(string)) +} - return nil +func flattenComputeUrlMapTest(v interface{}) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + transformed = append(transformed, map[string]interface{}{ + "description": flattenComputeUrlMapTestDescription(original["description"]), + "host": flattenComputeUrlMapTestHost(original["host"]), + "path": flattenComputeUrlMapTestPath(original["path"]), + "service": flattenComputeUrlMapTestService(original["service"]), + }) + } + return transformed +} +func flattenComputeUrlMapTestDescription(v interface{}) interface{} { + return v } -func resourceComputeUrlMapUpdate(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) +func flattenComputeUrlMapTestHost(v interface{}) interface{} { + return v +} - project, err := getProject(d, config) - if err != nil { - return err - } +func flattenComputeUrlMapTestPath(v interface{}) interface{} { + return v +} - name := d.Get("name").(string) - urlMap, err := config.clientCompute.UrlMaps.Get(project, name).Do() - if err != nil { - return fmt.Errorf("Error, failed to get Url Map %s: %s", name, err) +func flattenComputeUrlMapTestService(v interface{}) interface{} { + if v == nil { + return v } + return ConvertSelfLinkToV1(v.(string)) +} - urlMap.DefaultService = d.Get("default_service").(string) - - if v, ok := d.GetOk("description"); ok { - urlMap.Description = v.(string) - } +// ResourceRef only supports 1 type and UrlMap has references to a BackendBucket or BackendService. Just read the self_link string +// instead of extracting the name and making a self_link out of it. +func expandComputeUrlMapDefaultService(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} - if d.HasChange("host_rule") { - _oldHostRules, _newHostRules := d.GetChange("host_rule") - _oldHostRulesMap := make(map[string]interface{}) - _newHostRulesMap := make(map[string]interface{}) +func expandComputeUrlMapDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} - for _, v := range _oldHostRules.(*schema.Set).List() { - _hostRule := v.(map[string]interface{}) - _oldHostRulesMap[_hostRule["path_matcher"].(string)] = v +func expandComputeUrlMapHost_rule(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + v = v.(*schema.Set).List() + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue } - - for _, v := range _newHostRules.(*schema.Set).List() { - _hostRule := v.(map[string]interface{}) - _newHostRulesMap[_hostRule["path_matcher"].(string)] = v + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDescription, err := expandComputeUrlMapHost_ruleDescription(original["description"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDescription); val.IsValid() && !isEmptyValue(val) { + transformed["description"] = transformedDescription } - newHostRules := make([]*compute.HostRule, 0) - /* Decide which host rules to keep */ - for _, v := range urlMap.HostRules { - /* If it's in the old state, we have ownership over the host rule */ - if vOld, ok := _oldHostRulesMap[v.PathMatcher]; ok { - if vNew, ok := _newHostRulesMap[v.PathMatcher]; ok { - /* Adjust for any changes made to this rule */ - _newHostRule := vNew.(map[string]interface{}) - _oldHostRule := vOld.(map[string]interface{}) - _newHostsSet := make(map[string]bool) - _oldHostsSet := make(map[string]bool) - - hostRule := &compute.HostRule{ - PathMatcher: v.PathMatcher, - } - - for _, v := range _newHostRule["hosts"].([]interface{}) { - _newHostsSet[v.(string)] = true - } - - for _, v := range _oldHostRule["hosts"].([]interface{}) { - _oldHostsSet[v.(string)] = true - } - - /* Only add hosts that have been added locally or are new, - * not touching those from the GCE server state */ - for _, host := range v.Hosts { - _, okNew := _newHostsSet[host] - _, okOld := _oldHostsSet[host] - - /* Drop deleted hosts */ - if okOld && !okNew { - continue - } - - hostRule.Hosts = append(hostRule.Hosts, host) - - /* Kep track of the fact that this host was added */ - delete(_newHostsSet, host) - } - - /* Now add in the brand new entries */ - for host, _ := range _newHostsSet { - hostRule.Hosts = append(hostRule.Hosts, host) - } - - if v, ok := _newHostRule["description"]; ok { - hostRule.Description = v.(string) - } - - newHostRules = append(newHostRules, hostRule) - - /* Record that we've include this host rule */ - delete(_newHostRulesMap, v.PathMatcher) - } else { - /* It's been deleted */ - continue - } - } else { - if vNew, ok := _newHostRulesMap[v.PathMatcher]; ok { - newHostRules = append(newHostRules, createHostRule(vNew)) - - /* Record that we've include this host rule */ - delete(_newHostRulesMap, v.PathMatcher) - } else { - /* It wasn't created or modified locally */ - newHostRules = append(newHostRules, v) - } - } + transformedHosts, err := expandComputeUrlMapHost_ruleHosts(original["hosts"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHosts); val.IsValid() && !isEmptyValue(val) { + transformed["hosts"] = transformedHosts } - /* Record brand new host rules (ones not deleted above) */ - for _, v := range _newHostRulesMap { - newHostRules = append(newHostRules, createHostRule(v)) + transformedPathMatcher, err := expandComputeUrlMapHost_rulePathMatcher(original["path_matcher"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPathMatcher); val.IsValid() && !isEmptyValue(val) { + transformed["pathMatcher"] = transformedPathMatcher } - urlMap.HostRules = newHostRules + req = append(req, transformed) } + return req, nil +} + +func expandComputeUrlMapHost_ruleDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} - if d.HasChange("path_matcher") { - _oldPathMatchers, _newPathMatchers := d.GetChange("path_matcher") - _oldPathMatchersMap := make(map[string]interface{}) - _newPathMatchersMap := make(map[string]interface{}) +func expandComputeUrlMapHost_ruleHosts(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} - for _, v := range _oldPathMatchers.([]interface{}) { - _pathMatcher := v.(map[string]interface{}) - _oldPathMatchersMap[_pathMatcher["name"].(string)] = v +func expandComputeUrlMapHost_rulePathMatcher(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapFingerprint(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeUrlMapPath_matcher(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDefaultService, err := expandComputeUrlMapPath_matcherDefaultService(original["default_service"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDefaultService); val.IsValid() && !isEmptyValue(val) { + transformed["defaultService"] = transformedDefaultService } - for _, v := range _newPathMatchers.([]interface{}) { - _pathMatcher := v.(map[string]interface{}) - _newPathMatchersMap[_pathMatcher["name"].(string)] = v + transformedDescription, err := expandComputeUrlMapPath_matcherDescription(original["description"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDescription); val.IsValid() && !isEmptyValue(val) { + transformed["description"] = transformedDescription } - newPathMatchers := make([]*compute.PathMatcher, 0) - /* Decide which path matchers to keep */ - for _, v := range urlMap.PathMatchers { - /* If it's in the old state, we have ownership over the host rule */ - _, okOld := _oldPathMatchersMap[v.Name] - vNew, okNew := _newPathMatchersMap[v.Name] - - /* Drop deleted entries */ - if okOld && !okNew { - continue - } - - /* Don't change entries that don't belong to us */ - if !okNew { - newPathMatchers = append(newPathMatchers, v) - } else { - newPathMatchers = append(newPathMatchers, createPathMatcher(vNew)) - - delete(_newPathMatchersMap, v.Name) - } + transformedName, err := expandComputeUrlMapPath_matcherName(original["name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedName); val.IsValid() && !isEmptyValue(val) { + transformed["name"] = transformedName } - /* Record brand new host rules */ - for _, v := range _newPathMatchersMap { - newPathMatchers = append(newPathMatchers, createPathMatcher(v)) + transformedPath_rule, err := expandComputeUrlMapPath_matcherPath_rule(original["path_rule"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPath_rule); val.IsValid() && !isEmptyValue(val) { + transformed["pathRules"] = transformedPath_rule } - urlMap.PathMatchers = newPathMatchers + req = append(req, transformed) } + return req, nil +} - if d.HasChange("test") { - _oldTests, _newTests := d.GetChange("test") - _oldTestsMap := make(map[string]interface{}) - _newTestsMap := make(map[string]interface{}) +// ResourceRef only supports 1 type and UrlMap has references to a BackendBucket or BackendService. Just read the self_link string +// instead of extracting the name and making a self_link out of it. +func expandComputeUrlMapPath_matcherDefaultService(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} - for _, v := range _oldTests.([]interface{}) { - _test := v.(map[string]interface{}) - ident := fmt.Sprintf("%s/%s", _test["host"].(string), _test["path"].(string)) - _oldTestsMap[ident] = v - } +func expandComputeUrlMapPath_matcherDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} - for _, v := range _newTests.([]interface{}) { - _test := v.(map[string]interface{}) - ident := fmt.Sprintf("%s/%s", _test["host"].(string), _test["path"].(string)) - _newTestsMap[ident] = v - } +func expandComputeUrlMapPath_matcherName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} - newTests := make([]*compute.UrlMapTest, 0) - /* Decide which path matchers to keep */ - for _, v := range urlMap.Tests { - ident := fmt.Sprintf("%s/%s", v.Host, v.Path) - /* If it's in the old state, we have ownership over the host rule */ - _, okOld := _oldTestsMap[ident] - vNew, okNew := _newTestsMap[ident] - - /* Drop deleted entries */ - if okOld && !okNew { - continue - } - - /* Don't change entries that don't belong to us */ - if !okNew { - newTests = append(newTests, v) - } else { - newTests = append(newTests, createUrlMapTest(vNew)) - - delete(_newTestsMap, ident) - } +func expandComputeUrlMapPath_matcherPath_rule(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue } - - /* Record brand new host rules */ - for _, v := range _newTestsMap { - newTests = append(newTests, createUrlMapTest(v)) + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedPaths, err := expandComputeUrlMapPath_matcherPath_rulePaths(original["paths"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPaths); val.IsValid() && !isEmptyValue(val) { + transformed["paths"] = transformedPaths } - urlMap.Tests = newTests - } - op, err := config.clientCompute.UrlMaps.Update(project, urlMap.Name, urlMap).Do() + transformedService, err := expandComputeUrlMapPath_matcherPath_ruleService(original["service"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedService); val.IsValid() && !isEmptyValue(val) { + transformed["service"] = transformedService + } - if err != nil { - return fmt.Errorf("Error, failed to update Url Map %s: %s", name, err) + req = append(req, transformed) } + return req, nil +} - err = computeOperationWait(config.clientCompute, op, project, "Update Url Map") - - if err != nil { - return fmt.Errorf("Error, failed waitng to update Url Map %s: %s", name, err) - } +func expandComputeUrlMapPath_matcherPath_rulePaths(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} - return resourceComputeUrlMapRead(d, meta) +// ResourceRef only supports 1 type and UrlMap has references to a BackendBucket or BackendService. Just read the self_link string +// instead of extracting the name and making a self_link out of it. +func expandComputeUrlMapPath_matcherPath_ruleService(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil } -func resourceComputeUrlMapDelete(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) +func expandComputeUrlMapTest(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDescription, err := expandComputeUrlMapTestDescription(original["description"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDescription); val.IsValid() && !isEmptyValue(val) { + transformed["description"] = transformedDescription + } - project, err := getProject(d, config) - if err != nil { - return err - } + transformedHost, err := expandComputeUrlMapTestHost(original["host"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHost); val.IsValid() && !isEmptyValue(val) { + transformed["host"] = transformedHost + } - name := d.Get("name").(string) + transformedPath, err := expandComputeUrlMapTestPath(original["path"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPath); val.IsValid() && !isEmptyValue(val) { + transformed["path"] = transformedPath + } - op, err := config.clientCompute.UrlMaps.Delete(project, name).Do() + transformedService, err := expandComputeUrlMapTestService(original["service"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedService); val.IsValid() && !isEmptyValue(val) { + transformed["service"] = transformedService + } - if err != nil { - return fmt.Errorf("Error, failed to delete Url Map %s: %s", name, err) + req = append(req, transformed) } + return req, nil +} - err = computeOperationWait(config.clientCompute, op, project, "Delete Url Map") +func expandComputeUrlMapTestDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} - if err != nil { - return fmt.Errorf("Error, failed waitng to delete Url Map %s: %s", name, err) - } +func expandComputeUrlMapTestHost(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} - return nil +func expandComputeUrlMapTestPath(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil } -func resourceComputeUrlMapImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - d.Set("name", d.Id()) - return []*schema.ResourceData{d}, nil +// ResourceRef only supports 1 type and UrlMap has references to a BackendBucket or BackendService. Just read the self_link string +// instead of extracting the name and making a self_link out of it. +func expandComputeUrlMapTestService(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil } diff --git a/google/resource_compute_url_map_generated_test.go b/google/resource_compute_url_map_generated_test.go new file mode 100644 index 00000000000..36b05aafc72 --- /dev/null +++ b/google/resource_compute_url_map_generated_test.go @@ -0,0 +1,122 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccComputeUrlMap_urlMapBasicExample(t *testing.T) { + t.Parallel() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeUrlMapDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeUrlMap_urlMapBasicExample(acctest.RandString(10)), + }, + { + ResourceName: "google_compute_url_map.urlmap", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeUrlMap_urlMapBasicExample(val string) string { + return fmt.Sprintf(` +resource "google_compute_url_map" "urlmap" { + name = "urlmap-%s" + description = "a description" + + default_service = "${google_compute_backend_service.home.self_link}" + + host_rule { + hosts = ["mysite.com"] + path_matcher = "allpaths" + } + + path_matcher { + name = "allpaths" + default_service = "${google_compute_backend_service.home.self_link}" + + path_rule { + paths = ["/home"] + service = "${google_compute_backend_service.home.self_link}" + } + + path_rule { + paths = ["/login"] + service = "${google_compute_backend_service.login.self_link}" + } + + path_rule { + paths = ["/static"] + service = "${google_compute_backend_bucket.static.self_link}" + } + } + + test { + service = "${google_compute_backend_service.home.self_link}" + host = "hi.com" + path = "/home" + } +} + +resource "google_compute_backend_service" "login" { + name = "login-%s" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_http_health_check.default.self_link}"] +} + +resource "google_compute_backend_service" "home" { + name = "home-%s" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + + health_checks = ["${google_compute_http_health_check.default.self_link}"] +} + +resource "google_compute_http_health_check" "default" { + name = "health-check-%s" + request_path = "/" + check_interval_sec = 1 + timeout_sec = 1 +} + +resource "google_compute_backend_bucket" "static" { + name = "static-asset-backend-bucket-%s" + bucket_name = "${google_storage_bucket.static.name}" + enable_cdn = true +} + +resource "google_storage_bucket" "static" { + name = "static-asset-bucket-%s" + location = "US" +} +`, val, val, val, val, val, val, + ) +} diff --git a/google/resource_compute_vpn_tunnel.go b/google/resource_compute_vpn_tunnel.go index af7d02e1b01..acf940507de 100644 --- a/google/resource_compute_vpn_tunnel.go +++ b/google/resource_compute_vpn_tunnel.go @@ -313,6 +313,12 @@ func resourceComputeVpnTunnelCreate(d *schema.ResourceData, meta interface{}) er } else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) { obj["labels"] = labelsProp } + labelFingerprintProp, err := expandComputeVpnTunnelLabelFingerprint(d.Get("label_fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("label_fingerprint"); !isEmptyValue(reflect.ValueOf(labelFingerprintProp)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) { + obj["labelFingerprint"] = labelFingerprintProp + } regionProp, err := expandComputeVpnTunnelRegion(d.Get("region"), d, config) if err != nil { return err @@ -445,8 +451,12 @@ func resourceComputeVpnTunnelUpdate(d *schema.ResourceData, meta interface{}) er } else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { obj["labels"] = labelsProp } - labelFingerprintProp := d.Get("label_fingerprint") - obj["labelFingerprint"] = labelFingerprintProp + labelFingerprintProp, err := expandComputeVpnTunnelLabelFingerprint(d.Get("label_fingerprint"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("label_fingerprint"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) { + obj["labelFingerprint"] = labelFingerprintProp + } url, err := replaceVars(d, config, "https://www.googleapis.com/compute/beta/projects/{{project}}/regions/{{region}}/vpnTunnels/{{name}}/setLabels") if err != nil { @@ -672,6 +682,10 @@ func expandComputeVpnTunnelLabels(v interface{}, d *schema.ResourceData, config return m, nil } +func expandComputeVpnTunnelLabelFingerprint(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + func expandComputeVpnTunnelRegion(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { f, err := parseGlobalFieldValue("regions", v.(string), "project", d, config, true) if err != nil { diff --git a/website/docs/r/compute_forwarding_rule.html.markdown b/website/docs/r/compute_forwarding_rule.html.markdown index 85b6469eb28..9db2c9c8ea7 100644 --- a/website/docs/r/compute_forwarding_rule.html.markdown +++ b/website/docs/r/compute_forwarding_rule.html.markdown @@ -224,7 +224,7 @@ In addition to the arguments listed above, the following computed attributes are * `label_fingerprint` - The fingerprint used for optimistic locking of this resource. Used internally during updates. This property is in beta, and should be used with the terraform-provider-google-beta provider. - See [Provider Versions](https://terraform.io/docs/provider/google/provider_versions.html) for more details on beta fields. + See [Provider Versions](https://terraform.io/docs/providers/google/provider_versions.html) for more details on beta fields. * `service_name` - The internal fully qualified service name for this Forwarding Rule. diff --git a/website/docs/r/compute_global_address.html.markdown b/website/docs/r/compute_global_address.html.markdown index 01036b3294f..34fe0cea45f 100644 --- a/website/docs/r/compute_global_address.html.markdown +++ b/website/docs/r/compute_global_address.html.markdown @@ -118,7 +118,7 @@ In addition to the arguments listed above, the following computed attributes are * `label_fingerprint` - The fingerprint used for optimistic locking of this resource. Used internally during updates. This property is in beta, and should be used with the terraform-provider-google-beta provider. - See [Provider Versions](https://terraform.io/docs/provider/google/provider_versions.html) for more details on beta fields. + See [Provider Versions](https://terraform.io/docs/providers/google/provider_versions.html) for more details on beta fields. * `self_link` - The URI of the created resource. diff --git a/website/docs/r/compute_interconnect_attachment.html.markdown b/website/docs/r/compute_interconnect_attachment.html.markdown index a3aa96123a4..a104796ca33 100644 --- a/website/docs/r/compute_interconnect_attachment.html.markdown +++ b/website/docs/r/compute_interconnect_attachment.html.markdown @@ -25,6 +25,7 @@ Represents an InterconnectAttachment (VLAN attachment) resource. For more information, see Creating VLAN Attachments. + ## Example Usage ```hcl diff --git a/website/docs/r/compute_url_map.html.markdown b/website/docs/r/compute_url_map.html.markdown index 35114b2924a..59e41c62fc8 100644 --- a/website/docs/r/compute_url_map.html.markdown +++ b/website/docs/r/compute_url_map.html.markdown @@ -1,23 +1,36 @@ --- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in +# .github/CONTRIBUTING.md. +# +# ---------------------------------------------------------------------------- layout: "google" page_title: "Google: google_compute_url_map" sidebar_current: "docs-google-compute-url-map" description: |- - Manages a URL Map resource in GCE. + UrlMaps are used to route requests to a backend service based on rules + that you define for the host and path of an incoming URL. --- # google\_compute\_url\_map -Manages a URL Map resource within GCE. For more information see -[the official documentation](https://cloud.google.com/compute/docs/load-balancing/http/url-map) -and -[API](https://cloud.google.com/compute/docs/reference/latest/urlMaps). +UrlMaps are used to route requests to a backend service based on rules +that you define for the host and path of an incoming URL. + ## Example Usage ```hcl -resource "google_compute_url_map" "foobar" { +resource "google_compute_url_map" "urlmap" { name = "urlmap" description = "a description" @@ -56,7 +69,7 @@ resource "google_compute_url_map" "foobar" { } resource "google_compute_backend_service" "login" { - name = "login-backend" + name = "login" port_name = "http" protocol = "HTTP" timeout_sec = 10 @@ -65,7 +78,7 @@ resource "google_compute_backend_service" "login" { } resource "google_compute_backend_service" "home" { - name = "home-backend" + name = "home" port_name = "http" protocol = "HTTP" timeout_sec = 10 @@ -74,7 +87,7 @@ resource "google_compute_backend_service" "home" { } resource "google_compute_http_health_check" "default" { - name = "test" + name = "health-check" request_path = "/" check_interval_sec = 1 timeout_sec = 1 @@ -96,78 +109,148 @@ resource "google_storage_bucket" "static" { The following arguments are supported: -* `default_service` - (Required) The backend service or backend bucket to use when none of the given rules match. -* `name` - (Required) A unique name for the resource, required by GCE. - Changing this forces a new resource to be created. +* `default_service` - + (Required) + The backend service or backend bucket to use when none of the given rules match. + +* `name` - + (Required) + Name of the resource. Provided by the client when the resource is + created. The name must be 1-63 characters long, and comply with + RFC1035. Specifically, the name must be 1-63 characters long and match + the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the + first character must be a lowercase letter, and all following + characters must be a dash, lowercase letter, or digit, except the last + character, which cannot be a dash. + - - - -* `description` - (Optional) A brief description of this resource. -* `host_rule` - (Optional) A list of host rules. Multiple blocks of this type are permitted. Structure is documented below. +* `description` - + (Optional) + An optional description of this resource. Provide this property when + you create the resource. -* `path_matcher` - (Optional) A list of paths to match. Structure is documented below. +* `host_rule` - + (Optional) + The list of HostRules to use against the URL. Structure is documented below. -* `project` - (Optional) The ID of the project in which the resource belongs. If it - is not provided, the provider project is used. +* `path_matcher` - + (Optional) + The list of named PathMatchers to use against the URL. Structure is documented below. + +* `test` - + (Optional) + The list of expected URL mappings. Requests to update this UrlMap will + succeed only if all of the test cases pass. Structure is documented below. +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. -* `test` - (Optional) The test to perform. Multiple blocks of this type are permitted. Structure is documented below. The `host_rule` block supports: -* `hosts` (Required) - The list of [host patterns](https://cloud.google.com/compute/docs/reference/latest/urlMaps#hostRules.hosts) - to match. +* `description` - + (Optional) + An optional description of this HostRule. Provide this property + when you create the resource. -* `description` - (Optional) An optional description of the host rule. +* `hosts` - + (Required) + The list of host patterns to match. They must be valid + hostnames, except * will match any string of ([a-z0-9-.]*). In + that case, * must be the first character and must be followed in + the pattern by either - or .. -* `path_matcher` - (Required) The name of the `path_matcher` to apply this host rule to. +* `path_matcher` - + (Required) + The name of the PathMatcher to use to match the path portion of + the URL if the hostRule matches the URL's host portion. The `path_matcher` block supports: -* `name` - (Required) The name of the `path_matcher` resource. +* `default_service` - + (Required) + The backend service or backend bucket to use when none of the given paths match. + +* `description` - + (Optional) + An optional description of this resource. -* `default_service` - (Required) The backend service or backend bucket to use if none of the given paths match. +* `name` - + (Required) + The name to which this PathMatcher is referred by the HostRule. -* `description` - (Optional) An optional description of the host rule. +* `path_rule` - + (Optional) + The list of path rules. Structure is documented below. -* `path_rule` - (Optional) A list of path rules. Multiple blocks of this type are permitted. Structure is documented below. The `path_rule` block supports: -* `paths` - (Required) The list of [paths](https://cloud.google.com/compute/docs/reference/latest/urlMaps#pathMatchers.pathRules.paths) - to match against. +* `paths` - + (Optional) + The list of path patterns to match. Each must start with / + and the only place a * is allowed is at the end following + a /. The string fed to the path matcher does not include + any text after the first ? or #, and those chars are not + allowed here. -* `service` - (Required) The backend service or backend bucket to use if any of the given paths match. +* `service` - + (Required) + The backend service or backend bucket to use if any of the given paths match. The `test` block supports: -* `service` - (Required) The backend service or backend bucket link that should be matched by this test. +* `description` - + (Optional) + Description of this test case. -* `host` - (Required) The host component of the URL being tested. +* `host` - + (Required) + Host portion of the URL. -* `path` - (Required) The path component of the URL being tested. +* `path` - + (Required) + Path portion of the URL. -* `description` - (Optional) An optional description of this test. +* `service` - + (Required) + The backend service or backend bucket link that should be matched by this test. ## Attributes Reference -In addition to the arguments listed above, the following computed attributes are -exported: +In addition to the arguments listed above, the following computed attributes are exported: + -* `fingerprint` - The unique fingerprint for this resource. +* `creation_timestamp` - + Creation timestamp in RFC3339 text format. -* `map_id` - The GCE assigned ID of the resource. +* `map_id` - + The unique identifier for the resource. +* `fingerprint` - + Fingerprint of this resource. This field is used internally during + updates of this resource. * `self_link` - The URI of the created resource. + +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 4 minutes. +- `update` - Default is 4 minutes. +- `delete` - Default is 4 minutes. + ## Import -URL Map can be imported using the `name`, e.g. +UrlMap can be imported using any of these accepted formats: ``` -$ terraform import google_compute_url_map.html.foobar foobar +$ terraform import google_compute_url_map.default projects/{{project}}/global/urlMaps/{{name}} +$ terraform import google_compute_url_map.default {{project}}/{{name}} +$ terraform import google_compute_url_map.default {{name}} ``` - - -Currently `host_rule`, `path_matcher` and `test` importing is not yet supported.