github.com/IBM-Cloud/terraform@v0.6.4-0.20170726051544-8872b87621df/builtin/providers/google/resource_compute_vpn_tunnel.go (about)

     1  package google
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"net"
     7  
     8  	"github.com/hashicorp/terraform/helper/schema"
     9  
    10  	"google.golang.org/api/compute/v1"
    11  )
    12  
    13  func resourceComputeVpnTunnel() *schema.Resource {
    14  	return &schema.Resource{
    15  		// Unfortunately, the VPNTunnelService does not support update
    16  		// operations. This is why everything is marked forcenew
    17  		Create: resourceComputeVpnTunnelCreate,
    18  		Read:   resourceComputeVpnTunnelRead,
    19  		Delete: resourceComputeVpnTunnelDelete,
    20  
    21  		Schema: map[string]*schema.Schema{
    22  			"name": &schema.Schema{
    23  				Type:     schema.TypeString,
    24  				Required: true,
    25  				ForceNew: true,
    26  			},
    27  
    28  			"peer_ip": &schema.Schema{
    29  				Type:         schema.TypeString,
    30  				Required:     true,
    31  				ForceNew:     true,
    32  				ValidateFunc: validatePeerAddr,
    33  			},
    34  
    35  			"shared_secret": &schema.Schema{
    36  				Type:     schema.TypeString,
    37  				Required: true,
    38  				ForceNew: true,
    39  			},
    40  
    41  			"target_vpn_gateway": &schema.Schema{
    42  				Type:     schema.TypeString,
    43  				Required: true,
    44  				ForceNew: true,
    45  			},
    46  
    47  			"description": &schema.Schema{
    48  				Type:     schema.TypeString,
    49  				Optional: true,
    50  				ForceNew: true,
    51  			},
    52  
    53  			"detailed_status": &schema.Schema{
    54  				Type:     schema.TypeString,
    55  				Computed: true,
    56  			},
    57  
    58  			"ike_version": &schema.Schema{
    59  				Type:     schema.TypeInt,
    60  				Optional: true,
    61  				Default:  2,
    62  				ForceNew: true,
    63  			},
    64  
    65  			"local_traffic_selector": &schema.Schema{
    66  				Type:     schema.TypeSet,
    67  				Optional: true,
    68  				ForceNew: true,
    69  				Computed: true,
    70  				Elem:     &schema.Schema{Type: schema.TypeString},
    71  				Set:      schema.HashString,
    72  			},
    73  
    74  			"remote_traffic_selector": &schema.Schema{
    75  				Type:     schema.TypeSet,
    76  				Optional: true,
    77  				ForceNew: true,
    78  				Elem:     &schema.Schema{Type: schema.TypeString},
    79  				Set:      schema.HashString,
    80  			},
    81  
    82  			"project": &schema.Schema{
    83  				Type:     schema.TypeString,
    84  				Optional: true,
    85  				ForceNew: true,
    86  			},
    87  
    88  			"region": &schema.Schema{
    89  				Type:     schema.TypeString,
    90  				Optional: true,
    91  				ForceNew: true,
    92  			},
    93  
    94  			"self_link": &schema.Schema{
    95  				Type:     schema.TypeString,
    96  				Computed: true,
    97  			},
    98  		},
    99  	}
   100  }
   101  
   102  func resourceComputeVpnTunnelCreate(d *schema.ResourceData, meta interface{}) error {
   103  	config := meta.(*Config)
   104  
   105  	region, err := getRegion(d, config)
   106  	if err != nil {
   107  		return err
   108  	}
   109  
   110  	project, err := getProject(d, config)
   111  	if err != nil {
   112  		return err
   113  	}
   114  
   115  	name := d.Get("name").(string)
   116  	peerIp := d.Get("peer_ip").(string)
   117  	sharedSecret := d.Get("shared_secret").(string)
   118  	targetVpnGateway := d.Get("target_vpn_gateway").(string)
   119  	ikeVersion := d.Get("ike_version").(int)
   120  
   121  	if ikeVersion < 1 || ikeVersion > 2 {
   122  		return fmt.Errorf("Only IKE version 1 or 2 supported, not %d", ikeVersion)
   123  	}
   124  
   125  	// Build up the list of sources
   126  	var localTrafficSelectors []string
   127  	if v := d.Get("local_traffic_selector").(*schema.Set); v.Len() > 0 {
   128  		localTrafficSelectors = make([]string, v.Len())
   129  		for i, v := range v.List() {
   130  			localTrafficSelectors[i] = v.(string)
   131  		}
   132  	}
   133  
   134  	var remoteTrafficSelectors []string
   135  	if v := d.Get("remote_traffic_selector").(*schema.Set); v.Len() > 0 {
   136  		remoteTrafficSelectors = make([]string, v.Len())
   137  		for i, v := range v.List() {
   138  			remoteTrafficSelectors[i] = v.(string)
   139  		}
   140  	}
   141  
   142  	vpnTunnelsService := compute.NewVpnTunnelsService(config.clientCompute)
   143  
   144  	vpnTunnel := &compute.VpnTunnel{
   145  		Name:                  name,
   146  		PeerIp:                peerIp,
   147  		SharedSecret:          sharedSecret,
   148  		TargetVpnGateway:      targetVpnGateway,
   149  		IkeVersion:            int64(ikeVersion),
   150  		LocalTrafficSelector:  localTrafficSelectors,
   151  		RemoteTrafficSelector: remoteTrafficSelectors,
   152  	}
   153  
   154  	if v, ok := d.GetOk("description"); ok {
   155  		vpnTunnel.Description = v.(string)
   156  	}
   157  
   158  	op, err := vpnTunnelsService.Insert(project, region, vpnTunnel).Do()
   159  	if err != nil {
   160  		return fmt.Errorf("Error Inserting VPN Tunnel %s : %s", name, err)
   161  	}
   162  
   163  	err = computeOperationWaitRegion(config, op, project, region, "Inserting VPN Tunnel")
   164  	if err != nil {
   165  		return fmt.Errorf("Error Waiting to Insert VPN Tunnel %s: %s", name, err)
   166  	}
   167  
   168  	return resourceComputeVpnTunnelRead(d, meta)
   169  }
   170  
   171  func resourceComputeVpnTunnelRead(d *schema.ResourceData, meta interface{}) error {
   172  	config := meta.(*Config)
   173  
   174  	region, err := getRegion(d, config)
   175  	if err != nil {
   176  		return err
   177  	}
   178  
   179  	project, err := getProject(d, config)
   180  	if err != nil {
   181  		return err
   182  	}
   183  
   184  	name := d.Get("name").(string)
   185  
   186  	vpnTunnelsService := compute.NewVpnTunnelsService(config.clientCompute)
   187  
   188  	vpnTunnel, err := vpnTunnelsService.Get(project, region, name).Do()
   189  	if err != nil {
   190  		return handleNotFoundError(err, d, fmt.Sprintf("VPN Tunnel %q", d.Get("name").(string)))
   191  	}
   192  
   193  	localTrafficSelectors := []string{}
   194  	for _, lts := range vpnTunnel.LocalTrafficSelector {
   195  		localTrafficSelectors = append(localTrafficSelectors, lts)
   196  	}
   197  	d.Set("local_traffic_selector", localTrafficSelectors)
   198  
   199  	remoteTrafficSelectors := []string{}
   200  	for _, rts := range vpnTunnel.RemoteTrafficSelector {
   201  		remoteTrafficSelectors = append(remoteTrafficSelectors, rts)
   202  	}
   203  	d.Set("remote_traffic_selector", remoteTrafficSelectors)
   204  
   205  	d.Set("detailed_status", vpnTunnel.DetailedStatus)
   206  	d.Set("self_link", vpnTunnel.SelfLink)
   207  
   208  	d.SetId(name)
   209  
   210  	return nil
   211  }
   212  
   213  func resourceComputeVpnTunnelDelete(d *schema.ResourceData, meta interface{}) error {
   214  	config := meta.(*Config)
   215  
   216  	region, err := getRegion(d, config)
   217  	if err != nil {
   218  		return err
   219  	}
   220  
   221  	project, err := getProject(d, config)
   222  	if err != nil {
   223  		return err
   224  	}
   225  
   226  	name := d.Get("name").(string)
   227  
   228  	vpnTunnelsService := compute.NewVpnTunnelsService(config.clientCompute)
   229  
   230  	op, err := vpnTunnelsService.Delete(project, region, name).Do()
   231  	if err != nil {
   232  		return fmt.Errorf("Error Reading VPN Tunnel %s: %s", name, err)
   233  	}
   234  
   235  	err = computeOperationWaitRegion(config, op, project, region, "Deleting VPN Tunnel")
   236  	if err != nil {
   237  		return fmt.Errorf("Error Waiting to Delete VPN Tunnel %s: %s", name, err)
   238  	}
   239  
   240  	return nil
   241  }
   242  
   243  // validatePeerAddr returns false if a tunnel's peer_ip property
   244  // is invalid. Currently, only addresses that collide with RFC
   245  // 5735 (https://tools.ietf.org/html/rfc5735) fail validation.
   246  func validatePeerAddr(i interface{}, val string) ([]string, []error) {
   247  	ip := net.ParseIP(i.(string))
   248  	if ip == nil {
   249  		return nil, []error{fmt.Errorf("could not parse %q to IP address", val)}
   250  	}
   251  	for _, test := range invalidPeerAddrs {
   252  		if bytes.Compare(ip, test.from) >= 0 && bytes.Compare(ip, test.to) <= 0 {
   253  			return nil, []error{fmt.Errorf("address is invalid (is between %q and %q, conflicting with RFC5735)", test.from, test.to)}
   254  		}
   255  	}
   256  	return nil, nil
   257  }
   258  
   259  // invalidPeerAddrs is a collection of IP addres ranges that represent
   260  // a conflict with RFC 5735 (https://tools.ietf.org/html/rfc5735#page-3).
   261  // CIDR range notations in the RFC were converted to a (from, to) pair
   262  // for easy checking with bytes.Compare.
   263  var invalidPeerAddrs = []struct {
   264  	from net.IP
   265  	to   net.IP
   266  }{
   267  	{
   268  		from: net.ParseIP("0.0.0.0"),
   269  		to:   net.ParseIP("0.255.255.255"),
   270  	},
   271  	{
   272  		from: net.ParseIP("10.0.0.0"),
   273  		to:   net.ParseIP("10.255.255.255"),
   274  	},
   275  	{
   276  		from: net.ParseIP("127.0.0.0"),
   277  		to:   net.ParseIP("127.255.255.255"),
   278  	},
   279  	{
   280  		from: net.ParseIP("169.254.0.0"),
   281  		to:   net.ParseIP("169.254.255.255"),
   282  	},
   283  	{
   284  		from: net.ParseIP("172.16.0.0"),
   285  		to:   net.ParseIP("172.31.255.255"),
   286  	},
   287  	{
   288  		from: net.ParseIP("192.0.0.0"),
   289  		to:   net.ParseIP("192.0.0.255"),
   290  	},
   291  	{
   292  		from: net.ParseIP("192.0.2.0"),
   293  		to:   net.ParseIP("192.0.2.255"),
   294  	},
   295  	{
   296  		from: net.ParseIP("192.88.99.0"),
   297  		to:   net.ParseIP("192.88.99.255"),
   298  	},
   299  	{
   300  		from: net.ParseIP("192.168.0.0"),
   301  		to:   net.ParseIP("192.168.255.255"),
   302  	},
   303  	{
   304  		from: net.ParseIP("198.18.0.0"),
   305  		to:   net.ParseIP("198.19.255.255"),
   306  	},
   307  	{
   308  		from: net.ParseIP("198.51.100.0"),
   309  		to:   net.ParseIP("198.51.100.255"),
   310  	},
   311  	{
   312  		from: net.ParseIP("203.0.113.0"),
   313  		to:   net.ParseIP("203.0.113.255"),
   314  	},
   315  	{
   316  		from: net.ParseIP("224.0.0.0"),
   317  		to:   net.ParseIP("239.255.255.255"),
   318  	},
   319  	{
   320  		from: net.ParseIP("240.0.0.0"),
   321  		to:   net.ParseIP("255.255.255.255"),
   322  	},
   323  	{
   324  		from: net.ParseIP("255.255.255.255"),
   325  		to:   net.ParseIP("255.255.255.255"),
   326  	},
   327  }