Merge pull request #12411 from drebes/cloud_router
provider/google: Cloud router resource
This commit is contained in:
commit
63ce0dae98
|
@ -0,0 +1,28 @@
|
||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/acctest"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccComputeRouterInterface_import(t *testing.T) {
|
||||||
|
resourceName := "google_compute_router_interface.foobar"
|
||||||
|
testId := acctest.RandString(10)
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccComputeRouterInterfaceBasic(testId),
|
||||||
|
},
|
||||||
|
|
||||||
|
resource.TestStep{
|
||||||
|
ResourceName: resourceName,
|
||||||
|
ImportState: true,
|
||||||
|
ImportStateVerify: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/acctest"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccComputeRouterPeer_import(t *testing.T) {
|
||||||
|
resourceName := "google_compute_router_peer.foobar"
|
||||||
|
testId := acctest.RandString(10)
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccComputeRouterPeerBasic(testId),
|
||||||
|
},
|
||||||
|
|
||||||
|
resource.TestStep{
|
||||||
|
ResourceName: resourceName,
|
||||||
|
ImportState: true,
|
||||||
|
ImportStateVerify: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccComputeRouter_import(t *testing.T) {
|
||||||
|
resourceName := "google_compute_router.foobar"
|
||||||
|
resourceRegion := "europe-west1"
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckComputeRouterDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccComputeRouterBasic(resourceRegion),
|
||||||
|
},
|
||||||
|
|
||||||
|
resource.TestStep{
|
||||||
|
ResourceName: resourceName,
|
||||||
|
ImportState: true,
|
||||||
|
ImportStateVerify: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
|
@ -6,12 +6,16 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/mutexkv"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"google.golang.org/api/compute/v1"
|
"google.golang.org/api/compute/v1"
|
||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Global MutexKV
|
||||||
|
var mutexKV = mutexkv.NewMutexKV()
|
||||||
|
|
||||||
// Provider returns a terraform.ResourceProvider.
|
// Provider returns a terraform.ResourceProvider.
|
||||||
func Provider() terraform.ResourceProvider {
|
func Provider() terraform.ResourceProvider {
|
||||||
return &schema.Provider{
|
return &schema.Provider{
|
||||||
|
@ -82,6 +86,9 @@ func Provider() terraform.ResourceProvider {
|
||||||
"google_compute_project_metadata": resourceComputeProjectMetadata(),
|
"google_compute_project_metadata": resourceComputeProjectMetadata(),
|
||||||
"google_compute_region_backend_service": resourceComputeRegionBackendService(),
|
"google_compute_region_backend_service": resourceComputeRegionBackendService(),
|
||||||
"google_compute_route": resourceComputeRoute(),
|
"google_compute_route": resourceComputeRoute(),
|
||||||
|
"google_compute_router": resourceComputeRouter(),
|
||||||
|
"google_compute_router_interface": resourceComputeRouterInterface(),
|
||||||
|
"google_compute_router_peer": resourceComputeRouterPeer(),
|
||||||
"google_compute_ssl_certificate": resourceComputeSslCertificate(),
|
"google_compute_ssl_certificate": resourceComputeSslCertificate(),
|
||||||
"google_compute_subnetwork": resourceComputeSubnetwork(),
|
"google_compute_subnetwork": resourceComputeSubnetwork(),
|
||||||
"google_compute_target_http_proxy": resourceComputeTargetHttpProxy(),
|
"google_compute_target_http_proxy": resourceComputeTargetHttpProxy(),
|
||||||
|
@ -256,6 +263,10 @@ func getNetworkNameFromSelfLink(network string) (string, error) {
|
||||||
return network, nil
|
return network, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getRouterLockName(region string, router string) string {
|
||||||
|
return fmt.Sprintf("router/%s/%s", region, router)
|
||||||
|
}
|
||||||
|
|
||||||
func handleNotFoundError(err error, d *schema.ResourceData, resource string) error {
|
func handleNotFoundError(err error, d *schema.ResourceData, resource string) error {
|
||||||
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
|
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
|
||||||
log.Printf("[WARN] Removing %s because it's gone", resource)
|
log.Printf("[WARN] Removing %s because it's gone", resource)
|
||||||
|
@ -267,3 +278,11 @@ func handleNotFoundError(err error, d *schema.ResourceData, resource string) err
|
||||||
|
|
||||||
return fmt.Errorf("Error reading %s: %s", resource, err)
|
return fmt.Errorf("Error reading %s: %s", resource, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func linkDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
|
||||||
|
parts := strings.Split(old, "/")
|
||||||
|
if parts[len(parts)-1] == new {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package google
|
package google
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -87,3 +88,25 @@ func TestProvider_getRegionFromZone(t *testing.T) {
|
||||||
t.Fatalf("Region (%s) did not match expected value: %s", actual, expected)
|
t.Fatalf("Region (%s) did not match expected value: %s", actual, expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getTestRegion has the same logic as the provider's getRegion, to be used in tests.
|
||||||
|
func getTestRegion(is *terraform.InstanceState, config *Config) (string, error) {
|
||||||
|
if res, ok := is.Attributes["region"]; ok {
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
if config.Region != "" {
|
||||||
|
return config.Region, nil
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("%q: required field is not set", "region")
|
||||||
|
}
|
||||||
|
|
||||||
|
// getTestProject has the same logic as the provider's getProject, to be used in tests.
|
||||||
|
func getTestProject(is *terraform.InstanceState, config *Config) (string, error) {
|
||||||
|
if res, ok := is.Attributes["project"]; ok {
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
if config.Project != "" {
|
||||||
|
return config.Project, nil
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("%q: required field is not set", "project")
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,254 @@
|
||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"google.golang.org/api/compute/v1"
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceComputeRouter() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceComputeRouterCreate,
|
||||||
|
Read: resourceComputeRouterRead,
|
||||||
|
Delete: resourceComputeRouterDelete,
|
||||||
|
Importer: &schema.ResourceImporter{
|
||||||
|
State: resourceComputeRouterImportState,
|
||||||
|
},
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"network": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
DiffSuppressFunc: linkDiffSuppress,
|
||||||
|
},
|
||||||
|
|
||||||
|
"description": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"project": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"region": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"bgp": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
MaxItems: 1,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
|
||||||
|
"asn": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"self_link": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceComputeRouterCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
region, err := getRegion(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
project, err := getProject(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
name := d.Get("name").(string)
|
||||||
|
|
||||||
|
routerLock := getRouterLockName(region, name)
|
||||||
|
mutexKV.Lock(routerLock)
|
||||||
|
defer mutexKV.Unlock(routerLock)
|
||||||
|
|
||||||
|
network, err := getNetworkLink(d, config, "network")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
|
||||||
|
router := &compute.Router{
|
||||||
|
Name: name,
|
||||||
|
Network: network,
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("description"); ok {
|
||||||
|
router.Description = v.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := d.GetOk("bgp"); ok {
|
||||||
|
prefix := "bgp.0"
|
||||||
|
if v, ok := d.GetOk(prefix + ".asn"); ok {
|
||||||
|
asn := v.(int)
|
||||||
|
bgp := &compute.RouterBgp{
|
||||||
|
Asn: int64(asn),
|
||||||
|
}
|
||||||
|
router.Bgp = bgp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
op, err := routersService.Insert(project, region, router).Do()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error Inserting Router %s into network %s: %s", name, network, err)
|
||||||
|
}
|
||||||
|
d.SetId(fmt.Sprintf("%s/%s", region, name))
|
||||||
|
err = computeOperationWaitRegion(config, op, project, region, "Inserting Router")
|
||||||
|
if err != nil {
|
||||||
|
d.SetId("")
|
||||||
|
return fmt.Errorf("Error Waiting to Insert Router %s into network %s: %s", name, network, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceComputeRouterRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceComputeRouterRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
region, err := getRegion(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
project, err := getProject(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
name := d.Get("name").(string)
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
router, err := routersService.Get(project, region, name).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
|
||||||
|
log.Printf("[WARN] Removing router %s/%s because it is gone", region, name)
|
||||||
|
d.SetId("")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Error Reading Router %s: %s", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("self_link", router.SelfLink)
|
||||||
|
d.Set("network", router.Network)
|
||||||
|
|
||||||
|
d.Set("name", router.Name)
|
||||||
|
d.Set("description", router.Description)
|
||||||
|
d.Set("region", region)
|
||||||
|
d.Set("project", project)
|
||||||
|
d.Set("bgp", flattenAsn(router.Bgp.Asn))
|
||||||
|
d.SetId(fmt.Sprintf("%s/%s", region, name))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceComputeRouterDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
region, err := getRegion(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
project, err := getProject(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
name := d.Get("name").(string)
|
||||||
|
|
||||||
|
routerLock := getRouterLockName(region, name)
|
||||||
|
mutexKV.Lock(routerLock)
|
||||||
|
defer mutexKV.Unlock(routerLock)
|
||||||
|
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
|
||||||
|
op, err := routersService.Delete(project, region, name).Do()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error Reading Router %s: %s", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = computeOperationWaitRegion(config, op, project, region, "Deleting Router")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error Waiting to Delete Router %s: %s", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceComputeRouterImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
|
||||||
|
parts := strings.Split(d.Id(), "/")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return nil, fmt.Errorf("Invalid router specifier. Expecting {region}/{name}")
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("region", parts[0])
|
||||||
|
d.Set("name", parts[1])
|
||||||
|
|
||||||
|
return []*schema.ResourceData{d}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRouterLink(config *Config, project string, region string, router string) (string, error) {
|
||||||
|
|
||||||
|
if !strings.HasPrefix(router, "https://www.googleapis.com/compute/") {
|
||||||
|
// Router value provided is just the name, lookup the router SelfLink
|
||||||
|
routerData, err := config.clientCompute.Routers.Get(
|
||||||
|
project, region, router).Do()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Error reading router: %s", err)
|
||||||
|
}
|
||||||
|
router = routerData.SelfLink
|
||||||
|
}
|
||||||
|
|
||||||
|
return router, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func flattenAsn(asn int64) []map[string]interface{} {
|
||||||
|
result := make([]map[string]interface{}, 0, 1)
|
||||||
|
r := make(map[string]interface{})
|
||||||
|
r["asn"] = asn
|
||||||
|
result = append(result, r)
|
||||||
|
return result
|
||||||
|
}
|
|
@ -0,0 +1,269 @@
|
||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"google.golang.org/api/compute/v1"
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceComputeRouterInterface() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceComputeRouterInterfaceCreate,
|
||||||
|
Read: resourceComputeRouterInterfaceRead,
|
||||||
|
Delete: resourceComputeRouterInterfaceDelete,
|
||||||
|
Importer: &schema.ResourceImporter{
|
||||||
|
State: resourceComputeRouterInterfaceImportState,
|
||||||
|
},
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"router": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"vpn_tunnel": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
DiffSuppressFunc: linkDiffSuppress,
|
||||||
|
},
|
||||||
|
|
||||||
|
"ip_range": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"project": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"region": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceComputeRouterInterfaceCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
region, err := getRegion(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
project, err := getProject(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
routerName := d.Get("router").(string)
|
||||||
|
ifaceName := d.Get("name").(string)
|
||||||
|
|
||||||
|
routerLock := getRouterLockName(region, routerName)
|
||||||
|
mutexKV.Lock(routerLock)
|
||||||
|
defer mutexKV.Unlock(routerLock)
|
||||||
|
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
router, err := routersService.Get(project, region, routerName).Do()
|
||||||
|
if err != nil {
|
||||||
|
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
|
||||||
|
log.Printf("[WARN] Removing router interface %s because its router %s/%s is gone", ifaceName, region, routerName)
|
||||||
|
d.SetId("")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Error Reading router %s/%s: %s", region, routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ifaces := router.Interfaces
|
||||||
|
for _, iface := range ifaces {
|
||||||
|
if iface.Name == ifaceName {
|
||||||
|
d.SetId("")
|
||||||
|
return fmt.Errorf("Router %s has interface %s already", routerName, ifaceName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vpnTunnel, err := getVpnTunnelLink(config, project, region, d.Get("vpn_tunnel").(string))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
iface := &compute.RouterInterface{Name: ifaceName,
|
||||||
|
LinkedVpnTunnel: vpnTunnel}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("ip_range"); ok {
|
||||||
|
iface.IpRange = v.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[INFO] Adding interface %s", ifaceName)
|
||||||
|
ifaces = append(ifaces, iface)
|
||||||
|
patchRouter := &compute.Router{
|
||||||
|
Interfaces: ifaces,
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Updating router %s/%s with interfaces: %+v", region, routerName, ifaces)
|
||||||
|
op, err := routersService.Patch(project, region, router.Name, patchRouter).Do()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error patching router %s/%s: %s", region, routerName, err)
|
||||||
|
}
|
||||||
|
d.SetId(fmt.Sprintf("%s/%s/%s", region, routerName, ifaceName))
|
||||||
|
err = computeOperationWaitRegion(config, op, project, region, "Patching router")
|
||||||
|
if err != nil {
|
||||||
|
d.SetId("")
|
||||||
|
return fmt.Errorf("Error waiting to patch router %s/%s: %s", region, routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceComputeRouterInterfaceRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceComputeRouterInterfaceRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
region, err := getRegion(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
project, err := getProject(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
routerName := d.Get("router").(string)
|
||||||
|
ifaceName := d.Get("name").(string)
|
||||||
|
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
router, err := routersService.Get(project, region, routerName).Do()
|
||||||
|
if err != nil {
|
||||||
|
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
|
||||||
|
log.Printf("[WARN] Removing router interface %s because its router %s/%s is gone", ifaceName, region, routerName)
|
||||||
|
d.SetId("")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Error Reading router %s/%s: %s", region, routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, iface := range router.Interfaces {
|
||||||
|
|
||||||
|
if iface.Name == ifaceName {
|
||||||
|
d.SetId(fmt.Sprintf("%s/%s/%s", region, routerName, ifaceName))
|
||||||
|
d.Set("vpn_tunnel", iface.LinkedVpnTunnel)
|
||||||
|
d.Set("ip_range", iface.IpRange)
|
||||||
|
d.Set("region", region)
|
||||||
|
d.Set("project", project)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[WARN] Removing router interface %s/%s/%s because it is gone", region, routerName, ifaceName)
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceComputeRouterInterfaceDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
region, err := getRegion(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
project, err := getProject(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
routerName := d.Get("router").(string)
|
||||||
|
ifaceName := d.Get("name").(string)
|
||||||
|
|
||||||
|
routerLock := getRouterLockName(region, routerName)
|
||||||
|
mutexKV.Lock(routerLock)
|
||||||
|
defer mutexKV.Unlock(routerLock)
|
||||||
|
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
router, err := routersService.Get(project, region, routerName).Do()
|
||||||
|
if err != nil {
|
||||||
|
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
|
||||||
|
log.Printf("[WARN] Removing router interface %s because its router %s/%s is gone", ifaceName, region, routerName)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Error Reading Router %s: %s", routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ifaceFound bool
|
||||||
|
|
||||||
|
newIfaces := make([]*compute.RouterInterface, 0, len(router.Interfaces))
|
||||||
|
for _, iface := range router.Interfaces {
|
||||||
|
|
||||||
|
if iface.Name == ifaceName {
|
||||||
|
ifaceFound = true
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
newIfaces = append(newIfaces, iface)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ifaceFound {
|
||||||
|
log.Printf("[DEBUG] Router %s/%s had no interface %s already", region, routerName, ifaceName)
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf(
|
||||||
|
"[INFO] Removing interface %s from router %s/%s", ifaceName, region, routerName)
|
||||||
|
patchRouter := &compute.Router{
|
||||||
|
Interfaces: newIfaces,
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Updating router %s/%s with interfaces: %+v", region, routerName, newIfaces)
|
||||||
|
op, err := routersService.Patch(project, region, router.Name, patchRouter).Do()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error patching router %s/%s: %s", region, routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = computeOperationWaitRegion(config, op, project, region, "Patching router")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error waiting to patch router %s/%s: %s", region, routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceComputeRouterInterfaceImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
|
||||||
|
parts := strings.Split(d.Id(), "/")
|
||||||
|
if len(parts) != 3 {
|
||||||
|
return nil, fmt.Errorf("Invalid router interface specifier. Expecting {region}/{router}/{interface}")
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("region", parts[0])
|
||||||
|
d.Set("router", parts[1])
|
||||||
|
d.Set("name", parts[2])
|
||||||
|
|
||||||
|
return []*schema.ResourceData{d}, nil
|
||||||
|
}
|
|
@ -0,0 +1,282 @@
|
||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/acctest"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccComputeRouterInterface_basic(t *testing.T) {
|
||||||
|
testId := acctest.RandString(10)
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckComputeRouterInterfaceDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccComputeRouterInterfaceBasic(testId),
|
||||||
|
Check: testAccCheckComputeRouterInterfaceExists(
|
||||||
|
"google_compute_router_interface.foobar"),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccComputeRouterInterfaceKeepRouter(testId),
|
||||||
|
Check: testAccCheckComputeRouterInterfaceDelete(
|
||||||
|
"google_compute_router_interface.foobar"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckComputeRouterInterfaceDestroy(s *terraform.State) error {
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "google_compute_router" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
project, err := getTestProject(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
region, err := getTestRegion(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
routerName := rs.Primary.Attributes["router"]
|
||||||
|
|
||||||
|
_, err = routersService.Get(project, region, routerName).Do()
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("Error, Router %s in region %s still exists",
|
||||||
|
routerName, region)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckComputeRouterInterfaceDelete(n string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "google_compute_router_interface" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
project, err := getTestProject(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
region, err := getTestRegion(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
name := rs.Primary.Attributes["name"]
|
||||||
|
routerName := rs.Primary.Attributes["router"]
|
||||||
|
|
||||||
|
router, err := routersService.Get(project, region, routerName).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error Reading Router %s: %s", routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ifaces := router.Interfaces
|
||||||
|
for _, iface := range ifaces {
|
||||||
|
|
||||||
|
if iface.Name == name {
|
||||||
|
return fmt.Errorf("Interface %s still exists on router %s/%s", name, region, router.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckComputeRouterInterfaceExists(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)
|
||||||
|
|
||||||
|
project, err := getTestProject(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
region, err := getTestRegion(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
name := rs.Primary.Attributes["name"]
|
||||||
|
routerName := rs.Primary.Attributes["router"]
|
||||||
|
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
router, err := routersService.Get(project, region, routerName).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error Reading Router %s: %s", routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, iface := range router.Interfaces {
|
||||||
|
|
||||||
|
if iface.Name == name {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Interface %s not found for router %s", name, router.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccComputeRouterInterfaceBasic(testId string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "google_compute_network" "foobar" {
|
||||||
|
name = "router-interface-test-%s"
|
||||||
|
}
|
||||||
|
resource "google_compute_subnetwork" "foobar" {
|
||||||
|
name = "router-interface-test-%s"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
ip_cidr_range = "10.0.0.0/16"
|
||||||
|
region = "us-central1"
|
||||||
|
}
|
||||||
|
resource "google_compute_address" "foobar" {
|
||||||
|
name = "router-interface-test-%s"
|
||||||
|
region = "${google_compute_subnetwork.foobar.region}"
|
||||||
|
}
|
||||||
|
resource "google_compute_vpn_gateway" "foobar" {
|
||||||
|
name = "router-interface-test-%s"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
region = "${google_compute_subnetwork.foobar.region}"
|
||||||
|
}
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_esp" {
|
||||||
|
name = "router-interface-test-%s-1"
|
||||||
|
region = "${google_compute_vpn_gateway.foobar.region}"
|
||||||
|
ip_protocol = "ESP"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_udp500" {
|
||||||
|
name = "router-interface-test-%s-2"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_esp.region}"
|
||||||
|
ip_protocol = "UDP"
|
||||||
|
port_range = "500-500"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_udp4500" {
|
||||||
|
name = "router-interface-test-%s-3"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp500.region}"
|
||||||
|
ip_protocol = "UDP"
|
||||||
|
port_range = "4500-4500"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
resource "google_compute_router" "foobar"{
|
||||||
|
name = "router-interface-test-%s"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp500.region}"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
bgp {
|
||||||
|
asn = 64514
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resource "google_compute_vpn_tunnel" "foobar" {
|
||||||
|
name = "router-interface-test-%s"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp4500.region}"
|
||||||
|
target_vpn_gateway = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
shared_secret = "unguessable"
|
||||||
|
peer_ip = "8.8.8.8"
|
||||||
|
router = "${google_compute_router.foobar.name}"
|
||||||
|
}
|
||||||
|
resource "google_compute_router_interface" "foobar" {
|
||||||
|
name = "router-interface-test-%s"
|
||||||
|
router = "${google_compute_router.foobar.name}"
|
||||||
|
region = "${google_compute_router.foobar.region}"
|
||||||
|
ip_range = "169.254.3.1/30"
|
||||||
|
vpn_tunnel = "${google_compute_vpn_tunnel.foobar.name}"
|
||||||
|
}
|
||||||
|
`, testId, testId, testId, testId, testId, testId, testId, testId, testId, testId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccComputeRouterInterfaceKeepRouter(testId string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "google_compute_network" "foobar" {
|
||||||
|
name = "router-interface-test-%s"
|
||||||
|
}
|
||||||
|
resource "google_compute_subnetwork" "foobar" {
|
||||||
|
name = "router-interface-test-%s"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
ip_cidr_range = "10.0.0.0/16"
|
||||||
|
region = "us-central1"
|
||||||
|
}
|
||||||
|
resource "google_compute_address" "foobar" {
|
||||||
|
name = "router-interface-test-%s"
|
||||||
|
region = "${google_compute_subnetwork.foobar.region}"
|
||||||
|
}
|
||||||
|
resource "google_compute_vpn_gateway" "foobar" {
|
||||||
|
name = "router-interface-test-%s"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
region = "${google_compute_subnetwork.foobar.region}"
|
||||||
|
}
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_esp" {
|
||||||
|
name = "router-interface-test-%s-1"
|
||||||
|
region = "${google_compute_vpn_gateway.foobar.region}"
|
||||||
|
ip_protocol = "ESP"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_udp500" {
|
||||||
|
name = "router-interface-test-%s-2"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_esp.region}"
|
||||||
|
ip_protocol = "UDP"
|
||||||
|
port_range = "500-500"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_udp4500" {
|
||||||
|
name = "router-interface-test-%s-3"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp500.region}"
|
||||||
|
ip_protocol = "UDP"
|
||||||
|
port_range = "4500-4500"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
resource "google_compute_router" "foobar"{
|
||||||
|
name = "router-interface-test-%s"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp500.region}"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
bgp {
|
||||||
|
asn = 64514
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resource "google_compute_vpn_tunnel" "foobar" {
|
||||||
|
name = "router-interface-test-%s"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp4500.region}"
|
||||||
|
target_vpn_gateway = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
shared_secret = "unguessable"
|
||||||
|
peer_ip = "8.8.8.8"
|
||||||
|
router = "${google_compute_router.foobar.name}"
|
||||||
|
}
|
||||||
|
`, testId, testId, testId, testId, testId, testId, testId, testId, testId)
|
||||||
|
}
|
|
@ -0,0 +1,290 @@
|
||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"google.golang.org/api/compute/v1"
|
||||||
|
"google.golang.org/api/googleapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceComputeRouterPeer() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceComputeRouterPeerCreate,
|
||||||
|
Read: resourceComputeRouterPeerRead,
|
||||||
|
Delete: resourceComputeRouterPeerDelete,
|
||||||
|
Importer: &schema.ResourceImporter{
|
||||||
|
State: resourceComputeRouterPeerImportState,
|
||||||
|
},
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"router": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"interface": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"peer_ip_address": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"peer_asn": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"advertised_route_priority": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"ip_address": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"project": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"region": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceComputeRouterPeerCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
region, err := getRegion(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
project, err := getProject(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
routerName := d.Get("router").(string)
|
||||||
|
peerName := d.Get("name").(string)
|
||||||
|
|
||||||
|
routerLock := getRouterLockName(region, routerName)
|
||||||
|
mutexKV.Lock(routerLock)
|
||||||
|
defer mutexKV.Unlock(routerLock)
|
||||||
|
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
router, err := routersService.Get(project, region, routerName).Do()
|
||||||
|
if err != nil {
|
||||||
|
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
|
||||||
|
log.Printf("[WARN] Removing router peer %s because its router %s/%s is gone", peerName, region, routerName)
|
||||||
|
d.SetId("")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Error Reading router %s/%s: %s", region, routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
peers := router.BgpPeers
|
||||||
|
for _, peer := range peers {
|
||||||
|
if peer.Name == peerName {
|
||||||
|
d.SetId("")
|
||||||
|
return fmt.Errorf("Router %s has peer %s already", routerName, peerName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ifaceName := d.Get("interface").(string)
|
||||||
|
|
||||||
|
peer := &compute.RouterBgpPeer{Name: peerName,
|
||||||
|
InterfaceName: ifaceName}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("peer_ip_address"); ok {
|
||||||
|
peer.PeerIpAddress = v.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("peer_asn"); ok {
|
||||||
|
peer.PeerAsn = int64(v.(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("advertised_route_priority"); ok {
|
||||||
|
peer.AdvertisedRoutePriority = int64(v.(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[INFO] Adding peer %s", peerName)
|
||||||
|
peers = append(peers, peer)
|
||||||
|
patchRouter := &compute.Router{
|
||||||
|
BgpPeers: peers,
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Updating router %s/%s with peers: %+v", region, routerName, peers)
|
||||||
|
op, err := routersService.Patch(project, region, router.Name, patchRouter).Do()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error patching router %s/%s: %s", region, routerName, err)
|
||||||
|
}
|
||||||
|
d.SetId(fmt.Sprintf("%s/%s/%s", region, routerName, peerName))
|
||||||
|
err = computeOperationWaitRegion(config, op, project, region, "Patching router")
|
||||||
|
if err != nil {
|
||||||
|
d.SetId("")
|
||||||
|
return fmt.Errorf("Error waiting to patch router %s/%s: %s", region, routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceComputeRouterPeerRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceComputeRouterPeerRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
region, err := getRegion(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
project, err := getProject(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
routerName := d.Get("router").(string)
|
||||||
|
peerName := d.Get("name").(string)
|
||||||
|
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
router, err := routersService.Get(project, region, routerName).Do()
|
||||||
|
if err != nil {
|
||||||
|
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
|
||||||
|
log.Printf("[WARN] Removing router peer %s because its router %s/%s is gone", peerName, region, routerName)
|
||||||
|
d.SetId("")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Error Reading router %s/%s: %s", region, routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, peer := range router.BgpPeers {
|
||||||
|
|
||||||
|
if peer.Name == peerName {
|
||||||
|
d.SetId(fmt.Sprintf("%s/%s/%s", region, routerName, peerName))
|
||||||
|
d.Set("interface", peer.InterfaceName)
|
||||||
|
d.Set("peer_ip_address", peer.PeerIpAddress)
|
||||||
|
d.Set("peer_asn", peer.PeerAsn)
|
||||||
|
d.Set("advertised_route_priority", peer.AdvertisedRoutePriority)
|
||||||
|
d.Set("ip_address", peer.IpAddress)
|
||||||
|
d.Set("region", region)
|
||||||
|
d.Set("project", project)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[WARN] Removing router peer %s/%s/%s because it is gone", region, routerName, peerName)
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceComputeRouterPeerDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
region, err := getRegion(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
project, err := getProject(d, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
routerName := d.Get("router").(string)
|
||||||
|
peerName := d.Get("name").(string)
|
||||||
|
|
||||||
|
routerLock := getRouterLockName(region, routerName)
|
||||||
|
mutexKV.Lock(routerLock)
|
||||||
|
defer mutexKV.Unlock(routerLock)
|
||||||
|
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
router, err := routersService.Get(project, region, routerName).Do()
|
||||||
|
if err != nil {
|
||||||
|
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
|
||||||
|
log.Printf("[WARN] Removing router peer %s because its router %s/%s is gone", peerName, region, routerName)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Error Reading Router %s: %s", routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var newPeers []*compute.RouterBgpPeer = make([]*compute.RouterBgpPeer, 0, len(router.BgpPeers))
|
||||||
|
for _, peer := range router.BgpPeers {
|
||||||
|
if peer.Name == peerName {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
newPeers = append(newPeers, peer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(newPeers) == len(router.BgpPeers) {
|
||||||
|
log.Printf("[DEBUG] Router %s/%s had no peer %s already", region, routerName, peerName)
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf(
|
||||||
|
"[INFO] Removing peer %s from router %s/%s", peerName, region, routerName)
|
||||||
|
patchRouter := &compute.Router{
|
||||||
|
BgpPeers: newPeers,
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Updating router %s/%s with peers: %+v", region, routerName, newPeers)
|
||||||
|
op, err := routersService.Patch(project, region, router.Name, patchRouter).Do()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error patching router %s/%s: %s", region, routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = computeOperationWaitRegion(config, op, project, region, "Patching router")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error waiting to patch router %s/%s: %s", region, routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceComputeRouterPeerImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
|
||||||
|
parts := strings.Split(d.Id(), "/")
|
||||||
|
if len(parts) != 3 {
|
||||||
|
return nil, fmt.Errorf("Invalid router peer specifier. Expecting {region}/{router}/{peer}")
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("region", parts[0])
|
||||||
|
d.Set("router", parts[1])
|
||||||
|
d.Set("name", parts[2])
|
||||||
|
|
||||||
|
return []*schema.ResourceData{d}, nil
|
||||||
|
}
|
|
@ -0,0 +1,298 @@
|
||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/acctest"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccComputeRouterPeer_basic(t *testing.T) {
|
||||||
|
testId := acctest.RandString(10)
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckComputeRouterPeerDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccComputeRouterPeerBasic(testId),
|
||||||
|
Check: testAccCheckComputeRouterPeerExists(
|
||||||
|
"google_compute_router_peer.foobar"),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccComputeRouterPeerKeepRouter(testId),
|
||||||
|
Check: testAccCheckComputeRouterPeerDelete(
|
||||||
|
"google_compute_router_peer.foobar"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckComputeRouterPeerDestroy(s *terraform.State) error {
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "google_compute_router" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
project, err := getTestProject(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
region, err := getTestRegion(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
routerName := rs.Primary.Attributes["router"]
|
||||||
|
|
||||||
|
_, err = routersService.Get(project, region, routerName).Do()
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("Error, Router %s in region %s still exists",
|
||||||
|
routerName, region)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckComputeRouterPeerDelete(n string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "google_compute_router_peer" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
project, err := getTestProject(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
region, err := getTestRegion(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
name := rs.Primary.Attributes["name"]
|
||||||
|
routerName := rs.Primary.Attributes["router"]
|
||||||
|
|
||||||
|
router, err := routersService.Get(project, region, routerName).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error Reading Router %s: %s", routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
peers := router.BgpPeers
|
||||||
|
for _, peer := range peers {
|
||||||
|
|
||||||
|
if peer.Name == name {
|
||||||
|
return fmt.Errorf("Peer %s still exists on router %s/%s", name, region, router.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckComputeRouterPeerExists(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)
|
||||||
|
|
||||||
|
project, err := getTestProject(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
region, err := getTestRegion(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
name := rs.Primary.Attributes["name"]
|
||||||
|
routerName := rs.Primary.Attributes["router"]
|
||||||
|
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
router, err := routersService.Get(project, region, routerName).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error Reading Router %s: %s", routerName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, peer := range router.BgpPeers {
|
||||||
|
|
||||||
|
if peer.Name == name {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Peer %s not found for router %s", name, router.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccComputeRouterPeerBasic(testId string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "google_compute_network" "foobar" {
|
||||||
|
name = "router-peer-test-%s"
|
||||||
|
}
|
||||||
|
resource "google_compute_subnetwork" "foobar" {
|
||||||
|
name = "router-peer-test-%s"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
ip_cidr_range = "10.0.0.0/16"
|
||||||
|
region = "us-central1"
|
||||||
|
}
|
||||||
|
resource "google_compute_address" "foobar" {
|
||||||
|
name = "router-peer-test-%s"
|
||||||
|
region = "${google_compute_subnetwork.foobar.region}"
|
||||||
|
}
|
||||||
|
resource "google_compute_vpn_gateway" "foobar" {
|
||||||
|
name = "router-peer-test-%s"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
region = "${google_compute_subnetwork.foobar.region}"
|
||||||
|
}
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_esp" {
|
||||||
|
name = "router-peer-test-%s-1"
|
||||||
|
region = "${google_compute_vpn_gateway.foobar.region}"
|
||||||
|
ip_protocol = "ESP"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_udp500" {
|
||||||
|
name = "router-peer-test-%s-2"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_esp.region}"
|
||||||
|
ip_protocol = "UDP"
|
||||||
|
port_range = "500-500"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_udp4500" {
|
||||||
|
name = "router-peer-test-%s-3"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp500.region}"
|
||||||
|
ip_protocol = "UDP"
|
||||||
|
port_range = "4500-4500"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
resource "google_compute_router" "foobar"{
|
||||||
|
name = "router-peer-test-%s"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp500.region}"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
bgp {
|
||||||
|
asn = 64514
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resource "google_compute_vpn_tunnel" "foobar" {
|
||||||
|
name = "router-peer-test-%s"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp4500.region}"
|
||||||
|
target_vpn_gateway = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
shared_secret = "unguessable"
|
||||||
|
peer_ip = "8.8.8.8"
|
||||||
|
router = "${google_compute_router.foobar.name}"
|
||||||
|
}
|
||||||
|
resource "google_compute_router_interface" "foobar" {
|
||||||
|
name = "router-peer-test-%s"
|
||||||
|
router = "${google_compute_router.foobar.name}"
|
||||||
|
region = "${google_compute_router.foobar.region}"
|
||||||
|
ip_range = "169.254.3.1/30"
|
||||||
|
vpn_tunnel = "${google_compute_vpn_tunnel.foobar.name}"
|
||||||
|
}
|
||||||
|
resource "google_compute_router_peer" "foobar" {
|
||||||
|
name = "router-peer-test-%s"
|
||||||
|
router = "${google_compute_router.foobar.name}"
|
||||||
|
region = "${google_compute_router.foobar.region}"
|
||||||
|
peer_ip_address = "169.254.3.2"
|
||||||
|
peer_asn = 65515
|
||||||
|
advertised_route_priority = 100
|
||||||
|
interface = "${google_compute_router_interface.foobar.name}"
|
||||||
|
}
|
||||||
|
`, testId, testId, testId, testId, testId, testId, testId, testId, testId, testId, testId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccComputeRouterPeerKeepRouter(testId string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "google_compute_network" "foobar" {
|
||||||
|
name = "router-peer-test-%s"
|
||||||
|
}
|
||||||
|
resource "google_compute_subnetwork" "foobar" {
|
||||||
|
name = "router-peer-test-%s"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
ip_cidr_range = "10.0.0.0/16"
|
||||||
|
region = "us-central1"
|
||||||
|
}
|
||||||
|
resource "google_compute_address" "foobar" {
|
||||||
|
name = "router-peer-test-%s"
|
||||||
|
region = "${google_compute_subnetwork.foobar.region}"
|
||||||
|
}
|
||||||
|
resource "google_compute_vpn_gateway" "foobar" {
|
||||||
|
name = "router-peer-test-%s"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
region = "${google_compute_subnetwork.foobar.region}"
|
||||||
|
}
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_esp" {
|
||||||
|
name = "router-peer-test-%s-1"
|
||||||
|
region = "${google_compute_vpn_gateway.foobar.region}"
|
||||||
|
ip_protocol = "ESP"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_udp500" {
|
||||||
|
name = "router-peer-test-%s-2"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_esp.region}"
|
||||||
|
ip_protocol = "UDP"
|
||||||
|
port_range = "500-500"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_udp4500" {
|
||||||
|
name = "router-peer-test-%s-3"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp500.region}"
|
||||||
|
ip_protocol = "UDP"
|
||||||
|
port_range = "4500-4500"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
resource "google_compute_router" "foobar"{
|
||||||
|
name = "router-peer-test-%s"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp500.region}"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
bgp {
|
||||||
|
asn = 64514
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resource "google_compute_vpn_tunnel" "foobar" {
|
||||||
|
name = "router-peer-test-%s"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp4500.region}"
|
||||||
|
target_vpn_gateway = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
shared_secret = "unguessable"
|
||||||
|
peer_ip = "8.8.8.8"
|
||||||
|
router = "${google_compute_router.foobar.name}"
|
||||||
|
}
|
||||||
|
resource "google_compute_router_interface" "foobar" {
|
||||||
|
name = "router-peer-test-%s"
|
||||||
|
router = "${google_compute_router.foobar.name}"
|
||||||
|
region = "${google_compute_router.foobar.region}"
|
||||||
|
ip_range = "169.254.3.1/30"
|
||||||
|
vpn_tunnel = "${google_compute_vpn_tunnel.foobar.name}"
|
||||||
|
}
|
||||||
|
`, testId, testId, testId, testId, testId, testId, testId, testId, testId, testId)
|
||||||
|
}
|
|
@ -0,0 +1,202 @@
|
||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/acctest"
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccComputeRouter_basic(t *testing.T) {
|
||||||
|
resourceRegion := "europe-west1"
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckComputeRouterDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccComputeRouterBasic(resourceRegion),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckComputeRouterExists(
|
||||||
|
"google_compute_router.foobar"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"google_compute_router.foobar", "region", resourceRegion),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccComputeRouter_noRegion(t *testing.T) {
|
||||||
|
providerRegion := "us-central1"
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckComputeRouterDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccComputeRouterNoRegion(providerRegion),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckComputeRouterExists(
|
||||||
|
"google_compute_router.foobar"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"google_compute_router.foobar", "region", providerRegion),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccComputeRouter_networkLink(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckComputeRouterDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccComputeRouterNetworkLink(),
|
||||||
|
Check: testAccCheckComputeRouterExists(
|
||||||
|
"google_compute_router.foobar"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckComputeRouterDestroy(s *terraform.State) error {
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "google_compute_router" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
project, err := getTestProject(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
region, err := getTestRegion(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
name := rs.Primary.Attributes["name"]
|
||||||
|
|
||||||
|
_, err = routersService.Get(project, region, name).Do()
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("Error, Router %s in region %s still exists",
|
||||||
|
name, region)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckComputeRouterExists(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)
|
||||||
|
|
||||||
|
project, err := getTestProject(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
region, err := getTestRegion(rs.Primary, config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
name := rs.Primary.Attributes["name"]
|
||||||
|
|
||||||
|
routersService := config.clientCompute.Routers
|
||||||
|
_, err = routersService.Get(project, region, name).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error Reading Router %s: %s", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccComputeRouterBasic(resourceRegion string) string {
|
||||||
|
testId := acctest.RandString(10)
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "google_compute_network" "foobar" {
|
||||||
|
name = "router-test-%s"
|
||||||
|
}
|
||||||
|
resource "google_compute_subnetwork" "foobar" {
|
||||||
|
name = "router-test-%s"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
ip_cidr_range = "10.0.0.0/16"
|
||||||
|
region = "%s"
|
||||||
|
}
|
||||||
|
resource "google_compute_router" "foobar" {
|
||||||
|
name = "router-test-%s"
|
||||||
|
region = "${google_compute_subnetwork.foobar.region}"
|
||||||
|
network = "${google_compute_network.foobar.name}"
|
||||||
|
bgp {
|
||||||
|
asn = 64514
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`, testId, testId, resourceRegion, testId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccComputeRouterNoRegion(providerRegion string) string {
|
||||||
|
testId := acctest.RandString(10)
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "google_compute_network" "foobar" {
|
||||||
|
name = "router-test-%s"
|
||||||
|
}
|
||||||
|
resource "google_compute_subnetwork" "foobar" {
|
||||||
|
name = "router-test-%s"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
ip_cidr_range = "10.0.0.0/16"
|
||||||
|
region = "%s"
|
||||||
|
}
|
||||||
|
resource "google_compute_router" "foobar" {
|
||||||
|
name = "router-test-%s"
|
||||||
|
network = "${google_compute_network.foobar.name}"
|
||||||
|
bgp {
|
||||||
|
asn = 64514
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`, testId, testId, providerRegion, testId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccComputeRouterNetworkLink() string {
|
||||||
|
testId := acctest.RandString(10)
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "google_compute_network" "foobar" {
|
||||||
|
name = "router-test-%s"
|
||||||
|
}
|
||||||
|
resource "google_compute_subnetwork" "foobar" {
|
||||||
|
name = "router-test-%s"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
ip_cidr_range = "10.0.0.0/16"
|
||||||
|
region = "europe-west1"
|
||||||
|
}
|
||||||
|
resource "google_compute_router" "foobar" {
|
||||||
|
name = "router-test-%s"
|
||||||
|
region = "${google_compute_subnetwork.foobar.region}"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
bgp {
|
||||||
|
asn = 64514
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`, testId, testId, testId)
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
|
||||||
|
@ -75,6 +76,7 @@ func resourceComputeVpnTunnel() *schema.Resource {
|
||||||
Type: schema.TypeSet,
|
Type: schema.TypeSet,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
|
Computed: true,
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
Set: schema.HashString,
|
Set: schema.HashString,
|
||||||
},
|
},
|
||||||
|
@ -91,6 +93,12 @@ func resourceComputeVpnTunnel() *schema.Resource {
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"router": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
"self_link": &schema.Schema{
|
"self_link": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
|
@ -155,6 +163,14 @@ func resourceComputeVpnTunnelCreate(d *schema.ResourceData, meta interface{}) er
|
||||||
vpnTunnel.Description = v.(string)
|
vpnTunnel.Description = v.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("router"); ok {
|
||||||
|
routerLink, err := getRouterLink(config, project, region, v.(string))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
vpnTunnel.Router = routerLink
|
||||||
|
}
|
||||||
|
|
||||||
op, err := vpnTunnelsService.Insert(project, region, vpnTunnel).Do()
|
op, err := vpnTunnelsService.Insert(project, region, vpnTunnel).Do()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error Inserting VPN Tunnel %s : %s", name, err)
|
return fmt.Errorf("Error Inserting VPN Tunnel %s : %s", name, err)
|
||||||
|
@ -325,3 +341,33 @@ var invalidPeerAddrs = []struct {
|
||||||
to: net.ParseIP("255.255.255.255"),
|
to: net.ParseIP("255.255.255.255"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getVpnTunnelLink(config *Config, project string, region string, tunnel string) (string, error) {
|
||||||
|
|
||||||
|
if !strings.HasPrefix(tunnel, "https://www.googleapis.com/compute/") {
|
||||||
|
// Tunnel value provided is just the name, lookup the tunnel SelfLink
|
||||||
|
tunnelData, err := config.clientCompute.VpnTunnels.Get(
|
||||||
|
project, region, tunnel).Do()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Error reading tunnel: %s", err)
|
||||||
|
}
|
||||||
|
tunnel = tunnelData.SelfLink
|
||||||
|
}
|
||||||
|
|
||||||
|
return tunnel, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func getVpnTunnelName(vpntunnel string) (string, error) {
|
||||||
|
|
||||||
|
if strings.HasPrefix(vpntunnel, "https://www.googleapis.com/compute/") {
|
||||||
|
// extract the VPN tunnel name from SelfLink URL
|
||||||
|
vpntunnelName := vpntunnel[strings.LastIndex(vpntunnel, "/")+1:]
|
||||||
|
if vpntunnelName == "" {
|
||||||
|
return "", fmt.Errorf("VPN tunnel url not valid")
|
||||||
|
}
|
||||||
|
return vpntunnelName, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return vpntunnel, nil
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,26 @@ func TestAccComputeVpnTunnel_basic(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAccComputeVpnTunnel_router(t *testing.T) {
|
||||||
|
router := fmt.Sprintf("tunnel-test-router-%s", acctest.RandString(10))
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckComputeVpnTunnelDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccComputeVpnTunnelRouter(router),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckComputeVpnTunnelExists(
|
||||||
|
"google_compute_vpn_tunnel.foobar"),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"google_compute_vpn_tunnel.foobar", "router", router),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestAccComputeVpnTunnel_defaultTrafficSelectors(t *testing.T) {
|
func TestAccComputeVpnTunnel_defaultTrafficSelectors(t *testing.T) {
|
||||||
|
|
||||||
resource.Test(t, resource.TestCase{
|
resource.Test(t, resource.TestCase{
|
||||||
|
@ -154,6 +174,69 @@ resource "google_compute_vpn_tunnel" "foobar" {
|
||||||
acctest.RandString(10), acctest.RandString(10), acctest.RandString(10),
|
acctest.RandString(10), acctest.RandString(10), acctest.RandString(10),
|
||||||
acctest.RandString(10), acctest.RandString(10))
|
acctest.RandString(10), acctest.RandString(10))
|
||||||
|
|
||||||
|
func testAccComputeVpnTunnelRouter(router string) string {
|
||||||
|
testId := acctest.RandString(10)
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "google_compute_network" "foobar" {
|
||||||
|
name = "tunnel-test-%s"
|
||||||
|
}
|
||||||
|
resource "google_compute_subnetwork" "foobar" {
|
||||||
|
name = "tunnel-test-%s"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
ip_cidr_range = "10.0.0.0/16"
|
||||||
|
region = "us-central1"
|
||||||
|
}
|
||||||
|
resource "google_compute_address" "foobar" {
|
||||||
|
name = "tunnel-test-%s"
|
||||||
|
region = "${google_compute_subnetwork.foobar.region}"
|
||||||
|
}
|
||||||
|
resource "google_compute_vpn_gateway" "foobar" {
|
||||||
|
name = "tunnel-test-%s"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
region = "${google_compute_subnetwork.foobar.region}"
|
||||||
|
}
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_esp" {
|
||||||
|
name = "tunnel-test-%s-1"
|
||||||
|
region = "${google_compute_vpn_gateway.foobar.region}"
|
||||||
|
ip_protocol = "ESP"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_udp500" {
|
||||||
|
name = "tunnel-test-%s-2"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_esp.region}"
|
||||||
|
ip_protocol = "UDP"
|
||||||
|
port_range = "500-500"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_udp4500" {
|
||||||
|
name = "tunnel-test-%s-3"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp500.region}"
|
||||||
|
ip_protocol = "UDP"
|
||||||
|
port_range = "4500-4500"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
resource "google_compute_router" "foobar"{
|
||||||
|
name = "%s"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp500.region}"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
bgp {
|
||||||
|
asn = 64514
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resource "google_compute_vpn_tunnel" "foobar" {
|
||||||
|
name = "tunnel-test-%s"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp4500.region}"
|
||||||
|
target_vpn_gateway = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
shared_secret = "unguessable"
|
||||||
|
peer_ip = "8.8.8.8"
|
||||||
|
router = "${google_compute_router.foobar.name}"
|
||||||
|
}
|
||||||
|
`, testId, testId, testId, testId, testId, testId, testId, router, testId)
|
||||||
|
}
|
||||||
|
|
||||||
var testAccComputeVpnTunnelDefaultTrafficSelectors = fmt.Sprintf(`
|
var testAccComputeVpnTunnelDefaultTrafficSelectors = fmt.Sprintf(`
|
||||||
resource "google_compute_network" "foobar" {
|
resource "google_compute_network" "foobar" {
|
||||||
name = "tunnel-test-%s"
|
name = "tunnel-test-%s"
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
---
|
||||||
|
layout: "google"
|
||||||
|
page_title: "Google: google_compute_router"
|
||||||
|
sidebar_current: "docs-google-compute-router"
|
||||||
|
description: |-
|
||||||
|
Manages a Cloud Router resource.
|
||||||
|
---
|
||||||
|
|
||||||
|
# google\_compute\_router
|
||||||
|
|
||||||
|
Manages a Cloud Router resource. For more info, read the
|
||||||
|
[documentation](https://cloud.google.com/compute/docs/cloudrouter).
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "google_compute_network" "foobar" {
|
||||||
|
name = "network-1"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_compute_subnetwork" "foobar" {
|
||||||
|
name = "subnet-1"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
ip_cidr_range = "10.0.0.0/16"
|
||||||
|
region = "us-central1"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_compute_address" "foobar" {
|
||||||
|
name = "vpn-gateway-1-address"
|
||||||
|
region = "${google_compute_subnetwork.foobar.region}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_compute_vpn_gateway" "foobar" {
|
||||||
|
name = "vpn-gateway-1"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
region = "${google_compute_subnetwork.foobar.region}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_esp" {
|
||||||
|
name = "vpn-gw-1-esp"
|
||||||
|
region = "${google_compute_vpn_gateway.foobar.region}"
|
||||||
|
ip_protocol = "ESP"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_udp500" {
|
||||||
|
name = "vpn-gw-1-udp-500"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_esp.region}"
|
||||||
|
ip_protocol = "UDP"
|
||||||
|
port_range = "500-500"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_compute_forwarding_rule" "foobar_udp4500" {
|
||||||
|
name = "vpn-gw-1-udp-4500"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp500.region}"
|
||||||
|
ip_protocol = "UDP"
|
||||||
|
port_range = "4500-4500"
|
||||||
|
ip_address = "${google_compute_address.foobar.address}"
|
||||||
|
target = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_compute_router" "foobar" {
|
||||||
|
name = "router-1"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp500.region}"
|
||||||
|
network = "${google_compute_network.foobar.self_link}"
|
||||||
|
|
||||||
|
bgp {
|
||||||
|
asn = 64512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_compute_vpn_tunnel" "foobar" {
|
||||||
|
name = "vpn-tunnel-1"
|
||||||
|
region = "${google_compute_forwarding_rule.foobar_udp4500.region}"
|
||||||
|
target_vpn_gateway = "${google_compute_vpn_gateway.foobar.self_link}"
|
||||||
|
shared_secret = "unguessable"
|
||||||
|
peer_ip = "8.8.8.8"
|
||||||
|
router = "${google_compute_router.foobar.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_compute_router_interface" "foobar" {
|
||||||
|
name = "interface-1"
|
||||||
|
router = "${google_compute_router.foobar.name}"
|
||||||
|
region = "${google_compute_router.foobar.region}"
|
||||||
|
ip_range = "169.254.1.1/30"
|
||||||
|
vpn_tunnel = "${google_compute_vpn_tunnel.foobar.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_compute_router_peer" "foobar" {
|
||||||
|
name = "peer-1"
|
||||||
|
router = "${google_compute_router.foobar.name}"
|
||||||
|
region = "${google_compute_router.foobar.region}"
|
||||||
|
peer_ip_address = "169.254.1.2"
|
||||||
|
peer_asn = 65513
|
||||||
|
advertised_route_priority = 100
|
||||||
|
interface = "${google_compute_router_interface.foobar.name}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `name` - (Required) A unique name for the router, required by GCE. Changing
|
||||||
|
this forces a new router to be created.
|
||||||
|
|
||||||
|
* `network` - (Required) The name or resource link to the network this Cloud Router
|
||||||
|
will use to learn and announce routes. Changing this forces a new router to be created.
|
||||||
|
|
||||||
|
* `bgp` - (Required) BGP information specific to this router.
|
||||||
|
Changing this forces a new router to be created.
|
||||||
|
Structure is documented below.
|
||||||
|
|
||||||
|
- - -
|
||||||
|
|
||||||
|
* `description` - (Optional) A description of the resource.
|
||||||
|
Changing this forces a new router to be created.
|
||||||
|
|
||||||
|
* `project` - (Optional) The project in which the resource belongs. If it
|
||||||
|
is not provided, the provider project is used.
|
||||||
|
Changing this forces a new router to be created.
|
||||||
|
|
||||||
|
* `region` - (Optional) The region this router should sit in. If not specified,
|
||||||
|
the project region will be used. Changing this forces a new router to be
|
||||||
|
created.
|
||||||
|
|
||||||
|
- - -
|
||||||
|
|
||||||
|
The `bgp` block supports:
|
||||||
|
|
||||||
|
* `asn` - (Required) Local BGP Autonomous System Number (ASN). Must be an
|
||||||
|
RFC6996 private ASN.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
In addition to the arguments listed above, the following computed attributes are
|
||||||
|
exported:
|
||||||
|
|
||||||
|
* `self_link` - The URI of the created resource.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
Routers can be imported using the `region` and `name`, e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ terraform import google_compute_router.router-1 us-central1/router-1
|
||||||
|
```
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
---
|
||||||
|
layout: "google"
|
||||||
|
page_title: "Google: google_compute_router_interface"
|
||||||
|
sidebar_current: "docs-google-compute-router-interface"
|
||||||
|
description: |-
|
||||||
|
Manages a Cloud Router interface.
|
||||||
|
---
|
||||||
|
|
||||||
|
# google\_compute\_router_interface
|
||||||
|
|
||||||
|
Manages a Cloud Router interface. For more info, read the
|
||||||
|
[documentation](https://cloud.google.com/compute/docs/cloudrouter).
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "google_compute_router_interface" "foobar" {
|
||||||
|
name = "interface-1"
|
||||||
|
router = "router-1"
|
||||||
|
region = "us-central1"
|
||||||
|
ip_range = "169.254.1.1/30"
|
||||||
|
vpn_tunnel = "tunnel-1"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `name` - (Required) A unique name for the interface, required by GCE. Changing
|
||||||
|
this forces a new interface to be created.
|
||||||
|
|
||||||
|
* `router` - (Required) The name of the router this interface will be attached to.
|
||||||
|
Changing this forces a new interface to be created.
|
||||||
|
|
||||||
|
* `vpn_tunnel` - (Required) The name or resource link to the VPN tunnel this
|
||||||
|
interface will be linked to. Changing this forces a new interface to be created.
|
||||||
|
|
||||||
|
- - -
|
||||||
|
|
||||||
|
* `ip_range` - (Optional) IP address and range of the interface. The IP range must be
|
||||||
|
in the RFC3927 link-local IP space. Changing this forces a new interface to be created.
|
||||||
|
|
||||||
|
* `project` - (Optional) The project in which this interface's router belongs. If it
|
||||||
|
is not provided, the provider project is used. Changing this forces a new interface to be created.
|
||||||
|
|
||||||
|
* `region` - (Optional) The region this interface's router sits in. If not specified,
|
||||||
|
the project region will be used. Changing this forces a new interface to be
|
||||||
|
created.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
Only the arguments listed above are exposed as attributes.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
Router interfaces can be imported using the `region`, `router` and `name`, e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ terraform import google_compute_router_interface.interface-1 us-central1/router-1/interface-1
|
||||||
|
```
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
---
|
||||||
|
layout: "google"
|
||||||
|
page_title: "Google: google_compute_router_peer"
|
||||||
|
sidebar_current: "docs-google-compute-router-peer"
|
||||||
|
description: |-
|
||||||
|
Manages a Cloud Router BGP peer.
|
||||||
|
---
|
||||||
|
|
||||||
|
# google\_compute\_router
|
||||||
|
|
||||||
|
Manages a Cloud Router BGP peer. For more info, read the
|
||||||
|
[documentation](https://cloud.google.com/compute/docs/cloudrouter).
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "google_compute_router_peer" "foobar" {
|
||||||
|
name = "peer-1"
|
||||||
|
router = "router-1"
|
||||||
|
region = "us-central1"
|
||||||
|
peer_ip_address = "169.254.1.2"
|
||||||
|
peer_asn = 65513
|
||||||
|
advertised_route_priority = 100
|
||||||
|
interface = "interface-1"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `name` - (Required) A unique name for BGP peer, required by GCE. Changing
|
||||||
|
this forces a new peer to be created.
|
||||||
|
|
||||||
|
* `router` - (Required) The name of the router in which this BGP peer will be configured.
|
||||||
|
Changing this forces a new peer to be created.
|
||||||
|
|
||||||
|
* `interface` - (Required) The name of the interface the BGP peer is associated with.
|
||||||
|
Changing this forces a new peer to be created.
|
||||||
|
|
||||||
|
* `peer_ip_address` - (Required) IP address of the BGP interface outside Google Cloud.
|
||||||
|
Changing this forces a new peer to be created.
|
||||||
|
|
||||||
|
* `peer_asn` - (Required) Peer BGP Autonomous System Number (ASN).
|
||||||
|
Changing this forces a new peer to be created.
|
||||||
|
|
||||||
|
- - -
|
||||||
|
|
||||||
|
* `advertised_route_priority` - (Optional) The priority of routes advertised to this BGP peer.
|
||||||
|
Changing this forces a new peer to be created.
|
||||||
|
|
||||||
|
* `project` - (Optional) The project in which this peer's router belongs. If it
|
||||||
|
is not provided, the provider project is used. Changing this forces a new peer to be created.
|
||||||
|
|
||||||
|
* `region` - (Optional) The region this peer's router sits in. If not specified,
|
||||||
|
the project region will be used. Changing this forces a new peer to be
|
||||||
|
created.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
In addition to the arguments listed above, the following computed attributes are
|
||||||
|
exported:
|
||||||
|
|
||||||
|
* `ip_address` - IP address of the interface inside Google Cloud Platform.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
Router BGP peers can be imported using the `region`, `router` and `name`, e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ terraform import google_compute_router_peer.peer-1 us-central1/router-1/peer-1
|
||||||
|
```
|
|
@ -120,6 +120,10 @@ The following arguments are supported:
|
||||||
custom subnetted network. Refer to Google documentation for more
|
custom subnetted network. Refer to Google documentation for more
|
||||||
information.
|
information.
|
||||||
|
|
||||||
|
* `router` - (Optional) Name of a Cloud Router in the same region
|
||||||
|
to be used for dynamic routing. Refer to Google documentation for more
|
||||||
|
information.
|
||||||
|
|
||||||
* `project` - (Optional) The project in which the resource belongs. If it
|
* `project` - (Optional) The project in which the resource belongs. If it
|
||||||
is not provided, the provider project is used.
|
is not provided, the provider project is used.
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,18 @@
|
||||||
<a href="/docs/providers/google/r/compute_route.html">google_compute_route</a>
|
<a href="/docs/providers/google/r/compute_route.html">google_compute_route</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-google-compute-router") %>>
|
||||||
|
<a href="/docs/providers/google/r/compute_router.html">google_compute_router</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-google-compute-router-interface") %>>
|
||||||
|
<a href="/docs/providers/google/r/compute_router_interface.html">google_compute_router_interface</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-google-compute-router-peer") %>>
|
||||||
|
<a href="/docs/providers/google/r/compute_router_peer.html">google_compute_router_peer</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-google-compute-snapshot") %>>
|
<li<%= sidebar_current("docs-google-compute-snapshot") %>>
|
||||||
<a href="/docs/providers/google/r/compute_snapshot.html">google_compute_snapshot</a>
|
<a href="/docs/providers/google/r/compute_snapshot.html">google_compute_snapshot</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
Loading…
Reference in New Issue