Merge pull request #3722 from lwander/f-gcp-url-maps
provider/google: Added url map resource + tests & documentation
This commit is contained in:
commit
519756c42a
|
@ -17,8 +17,8 @@ import (
|
|||
"google.golang.org/api/compute/v1"
|
||||
"google.golang.org/api/container/v1"
|
||||
"google.golang.org/api/dns/v1"
|
||||
"google.golang.org/api/storage/v1"
|
||||
"google.golang.org/api/sqladmin/v1beta4"
|
||||
"google.golang.org/api/storage/v1"
|
||||
)
|
||||
|
||||
// Config is the configuration structure used to instantiate the Google
|
||||
|
|
|
@ -43,18 +43,19 @@ func Provider() terraform.ResourceProvider {
|
|||
"google_compute_global_address": resourceComputeGlobalAddress(),
|
||||
"google_compute_http_health_check": resourceComputeHttpHealthCheck(),
|
||||
"google_compute_instance": resourceComputeInstance(),
|
||||
"google_compute_instance_group_manager": resourceComputeInstanceGroupManager(),
|
||||
"google_compute_instance_template": resourceComputeInstanceTemplate(),
|
||||
"google_compute_network": resourceComputeNetwork(),
|
||||
"google_compute_project_metadata": resourceComputeProjectMetadata(),
|
||||
"google_compute_route": resourceComputeRoute(),
|
||||
"google_compute_ssl_certificate": resourceComputeSslCertificate(),
|
||||
"google_compute_target_pool": resourceComputeTargetPool(),
|
||||
"google_compute_url_map": resourceComputeUrlMap(),
|
||||
"google_compute_vpn_gateway": resourceComputeVpnGateway(),
|
||||
"google_compute_vpn_tunnel": resourceComputeVpnTunnel(),
|
||||
"google_container_cluster": resourceContainerCluster(),
|
||||
"google_dns_managed_zone": resourceDnsManagedZone(),
|
||||
"google_dns_record_set": resourceDnsRecordSet(),
|
||||
"google_compute_instance_group_manager": resourceComputeInstanceGroupManager(),
|
||||
"google_sql_database": resourceSqlDatabase(),
|
||||
"google_sql_database_instance": resourceSqlDatabaseInstance(),
|
||||
"google_storage_bucket": resourceStorageBucket(),
|
||||
|
|
|
@ -159,17 +159,17 @@ func resourceComputeInstanceTemplate() *schema.Resource {
|
|||
},
|
||||
|
||||
"automatic_restart": &schema.Schema{
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: true,
|
||||
ForceNew: true,
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: true,
|
||||
ForceNew: true,
|
||||
Deprecated: "Please use `scheduling.automatic_restart` instead",
|
||||
},
|
||||
|
||||
"on_host_maintenance": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Deprecated: "Please use `scheduling.on_host_maintenance` instead",
|
||||
},
|
||||
|
||||
|
@ -413,7 +413,6 @@ func resourceComputeInstanceTemplateCreate(d *schema.ResourceData, meta interfac
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
serviceAccountsCount := d.Get("service_account.#").(int)
|
||||
serviceAccounts := make([]*compute.ServiceAccount, 0, serviceAccountsCount)
|
||||
for i := 0; i < serviceAccountsCount; i++ {
|
||||
|
|
|
@ -0,0 +1,649 @@
|
|||
package google
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
func resourceComputeUrlMap() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceComputeUrlMapCreate,
|
||||
Read: resourceComputeUrlMapRead,
|
||||
Update: resourceComputeUrlMapUpdate,
|
||||
Delete: resourceComputeUrlMapDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"id": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"default_service": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"description": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
"fingerprint": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"host_rule": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"description": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
"hosts": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Required: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
},
|
||||
|
||||
"path_matcher": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"path_matcher": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"default_service": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"description": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"path_rule": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Required: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"paths": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Required: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
},
|
||||
|
||||
"service": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"self_link": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"test": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"description": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
"host": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"path": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"service": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func createHostRule(v interface{}) *compute.HostRule {
|
||||
_hostRule := v.(map[string]interface{})
|
||||
|
||||
_hosts := _hostRule["hosts"].([]interface{})
|
||||
hosts := make([]string, len(_hosts))
|
||||
|
||||
for i, v := range _hosts {
|
||||
hosts[i] = v.(string)
|
||||
}
|
||||
|
||||
pathMatcher := _hostRule["path_matcher"].(string)
|
||||
|
||||
hostRule := &compute.HostRule{
|
||||
Hosts: hosts,
|
||||
PathMatcher: pathMatcher,
|
||||
}
|
||||
|
||||
if v, ok := _hostRule["description"]; ok {
|
||||
hostRule.Description = v.(string)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
service := _pathRule["service"].(string)
|
||||
|
||||
pathRule := &compute.PathRule{
|
||||
Paths: paths,
|
||||
Service: service,
|
||||
}
|
||||
|
||||
pathRules[ip] = pathRule
|
||||
}
|
||||
|
||||
name := _pathMatcher["name"].(string)
|
||||
defaultService := _pathMatcher["default_service"].(string)
|
||||
|
||||
pathMatcher := &compute.PathMatcher{
|
||||
PathRules: pathRules,
|
||||
Name: name,
|
||||
DefaultService: defaultService,
|
||||
}
|
||||
|
||||
if vp, okp := _pathMatcher["description"]; okp {
|
||||
pathMatcher.Description = vp.(string)
|
||||
}
|
||||
|
||||
return pathMatcher
|
||||
}
|
||||
|
||||
func createUrlMapTest(v interface{}) *compute.UrlMapTest {
|
||||
_test := v.(map[string]interface{})
|
||||
|
||||
host := _test["host"].(string)
|
||||
path := _test["path"].(string)
|
||||
service := _test["service"].(string)
|
||||
|
||||
test := &compute.UrlMapTest{
|
||||
Host: host,
|
||||
Path: path,
|
||||
Service: service,
|
||||
}
|
||||
|
||||
if vp, okp := _test["description"]; okp {
|
||||
test.Description = vp.(string)
|
||||
}
|
||||
|
||||
return test
|
||||
}
|
||||
|
||||
func resourceComputeUrlMapCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
|
||||
name := d.Get("name").(string)
|
||||
defaultService := d.Get("default_service").(string)
|
||||
|
||||
urlMap := &compute.UrlMap{
|
||||
Name: name,
|
||||
DefaultService: defaultService,
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk("description"); ok {
|
||||
urlMap.Description = v.(string)
|
||||
}
|
||||
|
||||
_hostRules := d.Get("host_rule").([]interface{})
|
||||
urlMap.HostRules = make([]*compute.HostRule, len(_hostRules))
|
||||
|
||||
for i, v := range _hostRules {
|
||||
urlMap.HostRules[i] = createHostRule(v)
|
||||
}
|
||||
|
||||
_pathMatchers := d.Get("path_matcher").([]interface{})
|
||||
urlMap.PathMatchers = make([]*compute.PathMatcher, len(_pathMatchers))
|
||||
|
||||
for i, v := range _pathMatchers {
|
||||
urlMap.PathMatchers[i] = createPathMatcher(v)
|
||||
}
|
||||
|
||||
_tests := make([]interface{}, 0)
|
||||
if v, ok := d.GetOk("test"); ok {
|
||||
_tests = v.([]interface{})
|
||||
}
|
||||
urlMap.Tests = make([]*compute.UrlMapTest, len(_tests))
|
||||
|
||||
for i, v := range _tests {
|
||||
urlMap.Tests[i] = createUrlMapTest(v)
|
||||
}
|
||||
|
||||
op, err := config.clientCompute.UrlMaps.Insert(config.Project, urlMap).Do()
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error, failed to insert Url Map %s: %s", name, err)
|
||||
}
|
||||
|
||||
err = computeOperationWaitGlobal(config, op, "Insert Url Map")
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error, failed waitng to insert Url Map %s: %s", name, err)
|
||||
}
|
||||
|
||||
return resourceComputeUrlMapRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceComputeUrlMapRead(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
|
||||
name := d.Get("name").(string)
|
||||
|
||||
urlMap, err := config.clientCompute.UrlMaps.Get(config.Project, name).Do()
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error, failed to get Url Map %s: %s", name, err)
|
||||
}
|
||||
|
||||
d.SetId(name)
|
||||
d.Set("self_link", urlMap.SelfLink)
|
||||
d.Set("id", strconv.FormatUint(urlMap.Id, 10))
|
||||
d.Set("fingerprint", urlMap.Fingerprint)
|
||||
|
||||
hostRuleMap := make(map[string]*compute.HostRule)
|
||||
for _, v := range urlMap.HostRules {
|
||||
hostRuleMap[v.PathMatcher] = v
|
||||
}
|
||||
|
||||
/* Only read host rules into our TF state that we have defined */
|
||||
_hostRules := d.Get("host_rule").([]interface{})
|
||||
_newHostRules := make([]interface{}, 0)
|
||||
for _, v := range _hostRules {
|
||||
_hostRule := v.(map[string]interface{})
|
||||
_pathMatcher := _hostRule["path_matcher"].(string)
|
||||
|
||||
/* 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
|
||||
|
||||
hostsSet := make(map[string]bool)
|
||||
for _, host := range hostRule.Hosts {
|
||||
hostsSet[host] = true
|
||||
}
|
||||
|
||||
/* 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)
|
||||
}
|
||||
}
|
||||
|
||||
_newHostRule["hosts"] = _newHosts
|
||||
_newHostRule["description"] = hostRule.Description
|
||||
|
||||
_newHostRules = append(_newHostRules, _newHostRule)
|
||||
}
|
||||
}
|
||||
|
||||
d.Set("host_rule", _newHostRules)
|
||||
|
||||
pathMatcherMap := make(map[string]*compute.PathMatcher)
|
||||
for _, v := range urlMap.PathMatchers {
|
||||
pathMatcherMap[v.Name] = 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)
|
||||
|
||||
if pathMatcher, ok := pathMatcherMap[_name]; ok {
|
||||
_newPathMatcher := make(map[string]interface{})
|
||||
_newPathMatcher["name"] = _name
|
||||
_newPathMatcher["default_service"] = pathMatcher.DefaultService
|
||||
_newPathMatcher["description"] = pathMatcher.Description
|
||||
|
||||
_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))
|
||||
|
||||
for ipp, vpp := range pathRule.Paths {
|
||||
_paths[ipp] = vpp
|
||||
}
|
||||
|
||||
_newPathRule["paths"] = _paths
|
||||
|
||||
_newPathRules[ip] = _newPathRule
|
||||
}
|
||||
|
||||
_newPathMatcher["path_rule"] = _newPathRules
|
||||
_newPathMatchers = append(_newPathMatchers, _newPathMatcher)
|
||||
}
|
||||
}
|
||||
|
||||
d.Set("path_matcher", _newPathMatchers)
|
||||
|
||||
testMap := make(map[string]*compute.UrlMapTest)
|
||||
for _, v := range urlMap.Tests {
|
||||
testMap[fmt.Sprintf("%s/%s", v.Host, v.Path)] = 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{})
|
||||
}
|
||||
_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)
|
||||
}
|
||||
}
|
||||
|
||||
d.Set("test", _newTests)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceComputeUrlMapUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
|
||||
name := d.Get("name").(string)
|
||||
urlMap, err := config.clientCompute.UrlMaps.Get(config.Project, name).Do()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error, failed to get Url Map %s: %s", name, err)
|
||||
}
|
||||
|
||||
urlMap.DefaultService = d.Get("default_service").(string)
|
||||
|
||||
if v, ok := d.GetOk("description"); ok {
|
||||
urlMap.Description = v.(string)
|
||||
}
|
||||
|
||||
if d.HasChange("host_rule") {
|
||||
_oldHostRules, _newHostRules := d.GetChange("host_rule")
|
||||
_oldHostRulesMap := make(map[string]interface{})
|
||||
_newHostRulesMap := make(map[string]interface{})
|
||||
|
||||
for _, v := range _oldHostRules.([]interface{}) {
|
||||
_hostRule := v.(map[string]interface{})
|
||||
_oldHostRulesMap[_hostRule["path_matcher"].(string)] = v
|
||||
}
|
||||
|
||||
for _, v := range _newHostRules.([]interface{}) {
|
||||
_hostRule := v.(map[string]interface{})
|
||||
_newHostRulesMap[_hostRule["path_matcher"].(string)] = v
|
||||
}
|
||||
|
||||
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 _oldHostsSet {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Record brand new host rules (ones not deleted above) */
|
||||
for _, v := range _newHostRulesMap {
|
||||
newHostRules = append(newHostRules, createHostRule(v))
|
||||
}
|
||||
|
||||
urlMap.HostRules = newHostRules
|
||||
}
|
||||
|
||||
if d.HasChange("path_matcher") {
|
||||
_oldPathMatchers, _newPathMatchers := d.GetChange("path_matcher")
|
||||
_oldPathMatchersMap := make(map[string]interface{})
|
||||
_newPathMatchersMap := make(map[string]interface{})
|
||||
|
||||
for _, v := range _oldPathMatchers.([]interface{}) {
|
||||
_pathMatcher := v.(map[string]interface{})
|
||||
_oldPathMatchersMap[_pathMatcher["name"].(string)] = v
|
||||
}
|
||||
|
||||
for _, v := range _newPathMatchers.([]interface{}) {
|
||||
_pathMatcher := v.(map[string]interface{})
|
||||
_newPathMatchersMap[_pathMatcher["name"].(string)] = v
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
/* Record brand new host rules */
|
||||
for _, v := range _newPathMatchersMap {
|
||||
newPathMatchers = append(newPathMatchers, createPathMatcher(v))
|
||||
}
|
||||
|
||||
urlMap.PathMatchers = newPathMatchers
|
||||
}
|
||||
|
||||
if d.HasChange("tests") {
|
||||
_oldTests, _newTests := d.GetChange("path_matcher")
|
||||
_oldTestsMap := make(map[string]interface{})
|
||||
_newTestsMap := make(map[string]interface{})
|
||||
|
||||
for _, v := range _oldTests.([]interface{}) {
|
||||
_test := v.(map[string]interface{})
|
||||
ident := fmt.Sprintf("%s/%s", _test["host"].(string), _test["path"].(string))
|
||||
_oldTestsMap[ident] = v
|
||||
}
|
||||
|
||||
for _, v := range _newTests.([]interface{}) {
|
||||
_test := v.(map[string]interface{})
|
||||
ident := fmt.Sprintf("%s/%s", _test["host"].(string), _test["path"].(string))
|
||||
_newTestsMap[ident] = v
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
/* Record brand new host rules */
|
||||
for _, v := range _newTestsMap {
|
||||
newTests = append(newTests, createUrlMapTest(v))
|
||||
}
|
||||
|
||||
urlMap.Tests = newTests
|
||||
}
|
||||
|
||||
op, err := config.clientCompute.UrlMaps.Update(config.Project, urlMap.Name, urlMap).Do()
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error, failed to update Url Map %s: %s", name, err)
|
||||
}
|
||||
|
||||
err = computeOperationWaitGlobal(config, op, "Update Url Map")
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error, failed waitng to update Url Map %s: %s", name, err)
|
||||
}
|
||||
|
||||
return resourceComputeUrlMapRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceComputeUrlMapDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
name := d.Get("name").(string)
|
||||
|
||||
op, err := config.clientCompute.UrlMaps.Delete(config.Project, name).Do()
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error, failed to delete Url Map %s: %s", name, err)
|
||||
}
|
||||
|
||||
err = computeOperationWaitGlobal(config, op, "Delete Url Map")
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error, failed waitng to delete Url Map %s: %s", name, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,311 @@
|
|||
package google
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func TestAccComputeUrlMap_basic(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckComputeUrlMapDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccComputeUrlMap_basic1,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckComputeUrlMapExists(
|
||||
"google_compute_url_map.foobar"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccComputeUrlMap_update_path_matcher(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckComputeUrlMapDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccComputeUrlMap_basic1,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckComputeUrlMapExists(
|
||||
"google_compute_url_map.foobar"),
|
||||
),
|
||||
},
|
||||
|
||||
resource.TestStep{
|
||||
Config: testAccComputeUrlMap_basic2,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckComputeUrlMapExists(
|
||||
"google_compute_url_map.foobar"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccComputeUrlMap_advanced(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckComputeUrlMapDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccComputeUrlMap_advanced1,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckComputeUrlMapExists(
|
||||
"google_compute_url_map.foobar"),
|
||||
),
|
||||
},
|
||||
|
||||
resource.TestStep{
|
||||
Config: testAccComputeUrlMap_advanced2,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckComputeUrlMapExists(
|
||||
"google_compute_url_map.foobar"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckComputeUrlMapDestroy(s *terraform.State) error {
|
||||
config := testAccProvider.Meta().(*Config)
|
||||
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "google_compute_url_map" {
|
||||
continue
|
||||
}
|
||||
|
||||
_, err := config.clientCompute.UrlMaps.Get(
|
||||
config.Project, rs.Primary.ID).Do()
|
||||
if err == nil {
|
||||
return fmt.Errorf("Url map still exists")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func testAccCheckComputeUrlMapExists(n string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No ID is set")
|
||||
}
|
||||
|
||||
config := testAccProvider.Meta().(*Config)
|
||||
|
||||
found, err := config.clientCompute.UrlMaps.Get(
|
||||
config.Project, rs.Primary.ID).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if found.Name != rs.Primary.ID {
|
||||
return fmt.Errorf("Url map not found")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
const testAccComputeUrlMap_basic1 = `
|
||||
resource "google_compute_backend_service" "foobar" {
|
||||
name = "service"
|
||||
health_checks = ["${google_compute_http_health_check.zero.self_link}"]
|
||||
}
|
||||
|
||||
resource "google_compute_http_health_check" "zero" {
|
||||
name = "tf-test-zero"
|
||||
request_path = "/"
|
||||
check_interval_sec = 1
|
||||
timeout_sec = 1
|
||||
}
|
||||
|
||||
resource "google_compute_url_map" "foobar" {
|
||||
name = "myurlmap"
|
||||
default_service = "${google_compute_backend_service.foobar.self_link}"
|
||||
|
||||
host_rule {
|
||||
hosts = ["mysite.com", "myothersite.com"]
|
||||
path_matcher = "boop"
|
||||
}
|
||||
|
||||
path_matcher {
|
||||
default_service = "${google_compute_backend_service.foobar.self_link}"
|
||||
name = "boop"
|
||||
path_rule {
|
||||
paths = ["/*"]
|
||||
service = "${google_compute_backend_service.foobar.self_link}"
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
host = "mysite.com"
|
||||
path = "/*"
|
||||
service = "${google_compute_backend_service.foobar.self_link}"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const testAccComputeUrlMap_basic2 = `
|
||||
resource "google_compute_backend_service" "foobar" {
|
||||
name = "service"
|
||||
health_checks = ["${google_compute_http_health_check.zero.self_link}"]
|
||||
}
|
||||
|
||||
resource "google_compute_http_health_check" "zero" {
|
||||
name = "tf-test-zero"
|
||||
request_path = "/"
|
||||
check_interval_sec = 1
|
||||
timeout_sec = 1
|
||||
}
|
||||
|
||||
resource "google_compute_url_map" "foobar" {
|
||||
name = "myurlmap"
|
||||
default_service = "${google_compute_backend_service.foobar.self_link}"
|
||||
|
||||
host_rule {
|
||||
hosts = ["mysite.com", "myothersite.com"]
|
||||
path_matcher = "blip"
|
||||
}
|
||||
|
||||
path_matcher {
|
||||
default_service = "${google_compute_backend_service.foobar.self_link}"
|
||||
name = "blip"
|
||||
path_rule {
|
||||
paths = ["/*", "/home"]
|
||||
service = "${google_compute_backend_service.foobar.self_link}"
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
host = "mysite.com"
|
||||
path = "/*"
|
||||
service = "${google_compute_backend_service.foobar.self_link}"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const testAccComputeUrlMap_advanced1 = `
|
||||
resource "google_compute_backend_service" "foobar" {
|
||||
name = "service"
|
||||
health_checks = ["${google_compute_http_health_check.zero.self_link}"]
|
||||
}
|
||||
|
||||
resource "google_compute_http_health_check" "zero" {
|
||||
name = "tf-test-zero"
|
||||
request_path = "/"
|
||||
check_interval_sec = 1
|
||||
timeout_sec = 1
|
||||
}
|
||||
|
||||
resource "google_compute_url_map" "foobar" {
|
||||
name = "myurlmap"
|
||||
default_service = "${google_compute_backend_service.foobar.self_link}"
|
||||
|
||||
host_rule {
|
||||
hosts = ["mysite.com", "myothersite.com"]
|
||||
path_matcher = "blop"
|
||||
}
|
||||
|
||||
host_rule {
|
||||
hosts = ["myfavoritesite.com"]
|
||||
path_matcher = "blip"
|
||||
}
|
||||
|
||||
path_matcher {
|
||||
default_service = "${google_compute_backend_service.foobar.self_link}"
|
||||
name = "blop"
|
||||
path_rule {
|
||||
paths = ["/*", "/home"]
|
||||
service = "${google_compute_backend_service.foobar.self_link}"
|
||||
}
|
||||
}
|
||||
|
||||
path_matcher {
|
||||
default_service = "${google_compute_backend_service.foobar.self_link}"
|
||||
name = "blip"
|
||||
path_rule {
|
||||
paths = ["/*", "/home"]
|
||||
service = "${google_compute_backend_service.foobar.self_link}"
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const testAccComputeUrlMap_advanced2 = `
|
||||
resource "google_compute_backend_service" "foobar" {
|
||||
name = "service"
|
||||
health_checks = ["${google_compute_http_health_check.zero.self_link}"]
|
||||
}
|
||||
|
||||
resource "google_compute_http_health_check" "zero" {
|
||||
name = "tf-test-zero"
|
||||
request_path = "/"
|
||||
check_interval_sec = 1
|
||||
timeout_sec = 1
|
||||
}
|
||||
|
||||
resource "google_compute_url_map" "foobar" {
|
||||
name = "myurlmap"
|
||||
default_service = "${google_compute_backend_service.foobar.self_link}"
|
||||
|
||||
host_rule {
|
||||
hosts = ["mysite.com", "myothersite.com"]
|
||||
path_matcher = "blep"
|
||||
}
|
||||
|
||||
host_rule {
|
||||
hosts = ["myfavoritesite.com"]
|
||||
path_matcher = "blip"
|
||||
}
|
||||
|
||||
host_rule {
|
||||
hosts = ["myleastfavoritesite.com"]
|
||||
path_matcher = "blub"
|
||||
}
|
||||
|
||||
path_matcher {
|
||||
default_service = "${google_compute_backend_service.foobar.self_link}"
|
||||
name = "blep"
|
||||
path_rule {
|
||||
paths = ["/home"]
|
||||
service = "${google_compute_backend_service.foobar.self_link}"
|
||||
}
|
||||
|
||||
path_rule {
|
||||
paths = ["/login"]
|
||||
service = "${google_compute_backend_service.foobar.self_link}"
|
||||
}
|
||||
}
|
||||
|
||||
path_matcher {
|
||||
default_service = "${google_compute_backend_service.foobar.self_link}"
|
||||
name = "blub"
|
||||
path_rule {
|
||||
paths = ["/*", "/blub"]
|
||||
service = "${google_compute_backend_service.foobar.self_link}"
|
||||
}
|
||||
}
|
||||
|
||||
path_matcher {
|
||||
default_service = "${google_compute_backend_service.foobar.self_link}"
|
||||
name = "blip"
|
||||
path_rule {
|
||||
paths = ["/*", "/home"]
|
||||
service = "${google_compute_backend_service.foobar.self_link}"
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
|
@ -1,9 +1,8 @@
|
|||
package google
|
||||
|
||||
|
||||
import (
|
||||
"time"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
func genRandInt() int {
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
---
|
||||
layout: "google"
|
||||
page_title: "Google: google_compute_url_map"
|
||||
sidebar_current: "docs-google-resource-url-map"
|
||||
description: |-
|
||||
Manages a URL Map resource in GCE.
|
||||
---
|
||||
|
||||
# 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).
|
||||
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
resource "google_compute_url_map" "foobar" {
|
||||
name = "urlmap"
|
||||
description = "a description"
|
||||
default_service = "${google_compute_backend_service.home.self_link}"
|
||||
|
||||
host_rule {
|
||||
hosts = ["mysite.com"]
|
||||
path_matcher = "allpaths"
|
||||
}
|
||||
|
||||
path_matcher {
|
||||
default_service = "${google_compute_backend_service.home.self_link}"
|
||||
name = "allpaths"
|
||||
path_rule {
|
||||
paths = ["/home"]
|
||||
service = "${google_compute_backend_service.home.self_link}"
|
||||
}
|
||||
|
||||
path_rule {
|
||||
paths = ["/login"]
|
||||
service = "${google_compute_backend_service.login.self_link}"
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
service = "${google_compute_backend_service.home.self_link}"
|
||||
host = "hi.com"
|
||||
path = "/home"
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_compute_backend_service" "login" {
|
||||
name = "login-backend"
|
||||
port_name = "http"
|
||||
protocol = "HTTP"
|
||||
timeout_sec = 10
|
||||
region = "us-central1"
|
||||
|
||||
health_checks = ["${google_compute_http_health_check.default.self_link}"]
|
||||
}
|
||||
|
||||
resource "google_compute_backend_service" "home" {
|
||||
name = "home-backend"
|
||||
port_name = "http"
|
||||
protocol = "HTTP"
|
||||
timeout_sec = 10
|
||||
region = "us-central1"
|
||||
|
||||
health_checks = ["${google_compute_http_health_check.default.self_link}"]
|
||||
}
|
||||
|
||||
resource "google_compute_http_health_check" "default" {
|
||||
name = "test"
|
||||
request_path = "/"
|
||||
check_interval_sec = 1
|
||||
timeout_sec = 1
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `name` - (Required) A unique name for the resource, required by GCE.
|
||||
Changing this forces a new resource to be created.
|
||||
|
||||
* `description` - (Optional) A brief description of this resource.
|
||||
|
||||
* `default_service` - (Required) The URL of the backend service to use when none of the
|
||||
given rules match. See the documentation for formatting the service URL
|
||||
[here](https://cloud.google.com/compute/docs/reference/latest/urlMaps#defaultService)
|
||||
|
||||
The `host_rule` block supports: (Note that this block can be defined an arbitrary
|
||||
number of times.)
|
||||
|
||||
* `hosts` (Required) - A list of hosts to match against. See the documention
|
||||
for formatting each host [here](https://cloud.google.com/compute/docs/reference/latest/urlMaps#hostRules.hosts)
|
||||
|
||||
* `description` - (Optional) An optional description of the host rule.
|
||||
|
||||
* `path_matcher` - (Required) The name of the `path_matcher` (defined below)
|
||||
to apply this host rule to.
|
||||
|
||||
The `path_matcher` block supports: (Note that this block can be defined an arbitrary
|
||||
number of times.)
|
||||
|
||||
* `default_service` - (Required) The URL for the backend service to use if none
|
||||
of the given paths match. See the documentation for formatting the service URL
|
||||
[here](https://cloud.google.com/compute/docs/reference/latest/urlMaps#pathMatcher.defaultService)
|
||||
|
||||
* `name` - (Required) The name of the `path_matcher` resource. Used by the `host_rule`
|
||||
block above.
|
||||
|
||||
* `description` - (Optional) An optional description of the host rule.
|
||||
|
||||
The `path_matcher.path_rule` sub-block supports: (Note that this block can be defined an arbitrary
|
||||
number of times.)
|
||||
|
||||
* `paths` - (Required) The list of paths to match against. See the
|
||||
documentation for formatting these [here](https://cloud.google.com/compute/docs/reference/latest/urlMaps#pathMatchers.pathRules.paths)
|
||||
|
||||
* `default_service` - (Required) The URL for the backend service to use if any
|
||||
of the given paths match. See the documentation for formatting the service URL
|
||||
[here](https://cloud.google.com/compute/docs/reference/latest/urlMaps#pathMatcher.defaultService)
|
||||
|
||||
The optional `test` block supports: (Note that this block can be defined an arbitary
|
||||
number of times.)
|
||||
|
||||
* `service` - (Required) The service that should be matched by this test.
|
||||
|
||||
* `host` - (Required) The host component of the URL being tested.
|
||||
|
||||
* `path` - (Required) The path component of the URL being tested.
|
||||
|
||||
* `description` - (Optional) An optional description of this test.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
||||
* `id` - The GCE assigned ID of the resource.
|
||||
* `self_link` - A GCE assigned link to the resource.
|
|
@ -77,6 +77,10 @@
|
|||
<a href="/docs/providers/google/r/compute_target_pool.html">google_compute_target_pool</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-google-compute-url-map") %>>
|
||||
<a href="/docs/providers/google/r/compute_url_map.html">google_compute_url_map</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-google-compute-vpn-gateway") %>>
|
||||
<a href="/docs/providers/google/r/compute_vpn_gateway.html">google_compute_vpn_gateway</a>
|
||||
</li>
|
||||
|
|
Loading…
Reference in New Issue