Merge pull request #13123 from UKCloud/master
provider/vcd: Adding VPN Support to vCloud Provider
This commit is contained in:
commit
7d06a9bf43
|
@ -60,11 +60,12 @@ func Provider() terraform.ResourceProvider {
|
|||
},
|
||||
|
||||
ResourcesMap: map[string]*schema.Resource{
|
||||
"vcd_network": resourceVcdNetwork(),
|
||||
"vcd_vapp": resourceVcdVApp(),
|
||||
"vcd_firewall_rules": resourceVcdFirewallRules(),
|
||||
"vcd_dnat": resourceVcdDNAT(),
|
||||
"vcd_snat": resourceVcdSNAT(),
|
||||
"vcd_network": resourceVcdNetwork(),
|
||||
"vcd_vapp": resourceVcdVApp(),
|
||||
"vcd_firewall_rules": resourceVcdFirewallRules(),
|
||||
"vcd_dnat": resourceVcdDNAT(),
|
||||
"vcd_snat": resourceVcdSNAT(),
|
||||
"vcd_edgegateway_vpn": resourceVcdEdgeGatewayVpn(),
|
||||
},
|
||||
|
||||
ConfigureFunc: providerConfigure,
|
||||
|
|
|
@ -0,0 +1,290 @@
|
|||
package vcd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
types "github.com/ukcloud/govcloudair/types/v56"
|
||||
"log"
|
||||
)
|
||||
|
||||
func resourceVcdEdgeGatewayVpn() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceVcdEdgeGatewayVpnCreate,
|
||||
Read: resourceVcdEdgeGatewayVpnRead,
|
||||
Delete: resourceVcdEdgeGatewayVpnDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
|
||||
"edge_gateway": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"description": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"encryption_protocol": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"local_ip_address": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"local_id": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"mtu": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"peer_ip_address": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"peer_id": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"shared_secret": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"local_subnets": &schema.Schema{
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"local_subnet_name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"local_subnet_gateway": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"local_subnet_mask": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"peer_subnets": &schema.Schema{
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"peer_subnet_name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"peer_subnet_gateway": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"peer_subnet_mask": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceVcdEdgeGatewayVpnCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
vcdClient := meta.(*VCDClient)
|
||||
log.Printf("[TRACE] CLIENT: %#v", vcdClient)
|
||||
vcdClient.Mutex.Lock()
|
||||
defer vcdClient.Mutex.Unlock()
|
||||
|
||||
edgeGateway, err := vcdClient.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string))
|
||||
|
||||
localSubnetsList := d.Get("local_subnets").(*schema.Set).List()
|
||||
peerSubnetsList := d.Get("peer_subnets").(*schema.Set).List()
|
||||
|
||||
localSubnets := make([]*types.IpsecVpnSubnet, len(localSubnetsList))
|
||||
peerSubnets := make([]*types.IpsecVpnSubnet, len(peerSubnetsList))
|
||||
|
||||
for i, s := range localSubnetsList {
|
||||
ls := s.(map[string]interface{})
|
||||
localSubnets[i] = &types.IpsecVpnSubnet{
|
||||
Name: ls["local_subnet_name"].(string),
|
||||
Gateway: ls["local_subnet_gateway"].(string),
|
||||
Netmask: ls["local_subnet_mask"].(string),
|
||||
}
|
||||
}
|
||||
|
||||
for i, s := range peerSubnetsList {
|
||||
ls := s.(map[string]interface{})
|
||||
peerSubnets[i] = &types.IpsecVpnSubnet{
|
||||
Name: ls["peer_subnet_name"].(string),
|
||||
Gateway: ls["peer_subnet_gateway"].(string),
|
||||
Netmask: ls["peer_subnet_mask"].(string),
|
||||
}
|
||||
}
|
||||
|
||||
tunnel := &types.GatewayIpsecVpnTunnel{
|
||||
Name: d.Get("name").(string),
|
||||
Description: d.Get("description").(string),
|
||||
IpsecVpnLocalPeer: &types.IpsecVpnLocalPeer{
|
||||
ID: "",
|
||||
Name: "",
|
||||
},
|
||||
EncryptionProtocol: d.Get("encryption_protocol").(string),
|
||||
LocalIPAddress: d.Get("local_ip_address").(string),
|
||||
LocalID: d.Get("local_id").(string),
|
||||
LocalSubnet: localSubnets,
|
||||
Mtu: d.Get("mtu").(int),
|
||||
PeerID: d.Get("peer_id").(string),
|
||||
PeerIPAddress: d.Get("peer_ip_address").(string),
|
||||
PeerSubnet: peerSubnets,
|
||||
SharedSecret: d.Get("shared_secret").(string),
|
||||
IsEnabled: true,
|
||||
}
|
||||
|
||||
tunnels := make([]*types.GatewayIpsecVpnTunnel, 1)
|
||||
tunnels[0] = tunnel
|
||||
|
||||
ipsecVPNConfig := &types.EdgeGatewayServiceConfiguration{
|
||||
Xmlns: "http://www.vmware.com/vcloud/v1.5",
|
||||
GatewayIpsecVpnService: &types.GatewayIpsecVpnService{
|
||||
IsEnabled: true,
|
||||
Tunnel: tunnels,
|
||||
},
|
||||
}
|
||||
|
||||
log.Printf("[INFO] ipsecVPNConfig: %#v", ipsecVPNConfig)
|
||||
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
edgeGateway.Refresh()
|
||||
task, err := edgeGateway.AddIpsecVPN(ipsecVPNConfig)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Error setting ipsecVPNConfig rules: %s", err)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("Error setting ipsecVPNConfig rules: %#v", err))
|
||||
}
|
||||
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error completing tasks: %#v", err)
|
||||
}
|
||||
|
||||
d.SetId(d.Get("edge_gateway").(string))
|
||||
|
||||
return resourceVcdEdgeGatewayVpnRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceVcdEdgeGatewayVpnDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
vcdClient := meta.(*VCDClient)
|
||||
|
||||
log.Printf("[TRACE] CLIENT: %#v", vcdClient)
|
||||
|
||||
vcdClient.Mutex.Lock()
|
||||
defer vcdClient.Mutex.Unlock()
|
||||
|
||||
edgeGateway, err := vcdClient.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string))
|
||||
|
||||
ipsecVPNConfig := &types.EdgeGatewayServiceConfiguration{
|
||||
Xmlns: "http://www.vmware.com/vcloud/v1.5",
|
||||
GatewayIpsecVpnService: &types.GatewayIpsecVpnService{
|
||||
IsEnabled: false,
|
||||
},
|
||||
}
|
||||
|
||||
log.Printf("[INFO] ipsecVPNConfig: %#v", ipsecVPNConfig)
|
||||
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
edgeGateway.Refresh()
|
||||
task, err := edgeGateway.AddIpsecVPN(ipsecVPNConfig)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Error setting ipsecVPNConfig rules: %s", err)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("Error setting ipsecVPNConfig rules: %#v", err))
|
||||
}
|
||||
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error completing tasks: %#v", err)
|
||||
}
|
||||
|
||||
d.SetId(d.Get("edge_gateway").(string))
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error finding edge gateway: %#v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceVcdEdgeGatewayVpnRead(d *schema.ResourceData, meta interface{}) error {
|
||||
vcdClient := meta.(*VCDClient)
|
||||
|
||||
edgeGateway, err := vcdClient.OrgVdc.FindEdgeGateway(d.Get("edge_gateway").(string))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error finding edge gateway: %#v", err)
|
||||
}
|
||||
|
||||
egsc := edgeGateway.EdgeGateway.Configuration.EdgeGatewayServiceConfiguration.GatewayIpsecVpnService
|
||||
|
||||
if len(egsc.Tunnel) == 0 {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(egsc.Tunnel) == 1 {
|
||||
tunnel := egsc.Tunnel[0]
|
||||
d.Set("name", tunnel.Name)
|
||||
d.Set("description", tunnel.Description)
|
||||
d.Set("encryption_protocol", tunnel.EncryptionProtocol)
|
||||
d.Set("local_ip_address", tunnel.LocalIPAddress)
|
||||
d.Set("local_id", tunnel.LocalID)
|
||||
d.Set("mtu", tunnel.Mtu)
|
||||
d.Set("peer_ip_address", tunnel.PeerIPAddress)
|
||||
d.Set("peer_id", tunnel.PeerID)
|
||||
d.Set("shared_secret", tunnel.SharedSecret)
|
||||
d.Set("local_subnets", tunnel.LocalSubnet)
|
||||
d.Set("peer_subnets", tunnel.PeerSubnet)
|
||||
} else {
|
||||
return fmt.Errorf("Multiple tunnels not currently supported")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package vcd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func TestAccVcdVpn_Basic(t *testing.T) {
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckVcdVpnDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: fmt.Sprintf(testAccCheckVcdVpn_basic, os.Getenv("VCD_EDGE_GATEWAY")),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(
|
||||
"vcd_edgegateway_vpn.vpn", "encryption_protocol", "AES256"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckVcdVpnDestroy(s *terraform.State) error {
|
||||
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "vcd_edgegateway_vpn" {
|
||||
continue
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const testAccCheckVcdVpn_basic = `
|
||||
resource "vcd_edgegateway_vpn" "vpn" {
|
||||
edge_gateway = "%s"
|
||||
name = "west-to-east"
|
||||
description = "Description"
|
||||
encryption_protocol = "AES256"
|
||||
mtu = 1400
|
||||
peer_id = "51.179.218.195"
|
||||
peer_ip_address = "51.179.218.195"
|
||||
local_id = "51.179.218.196"
|
||||
local_ip_address = "51.179.218.196"
|
||||
shared_secret = "yZ4B8pxS5334m6ho692hjbtb7zo2vbesn7pe8ry5hyud86M433tbnnfxt6Dqn73g"
|
||||
|
||||
peer_subnets {
|
||||
peer_subnet_name = "DMZ_WEST"
|
||||
peer_subnet_gateway = "10.0.10.1"
|
||||
peer_subnet_mask = "255.255.255.0"
|
||||
}
|
||||
|
||||
peer_subnets {
|
||||
peer_subnet_name = "WEB_WEST"
|
||||
peer_subnet_gateway = "10.0.20.1"
|
||||
peer_subnet_mask = "255.255.255.0"
|
||||
}
|
||||
|
||||
local_subnets {
|
||||
local_subnet_name = "DMZ_EAST"
|
||||
local_subnet_gateway = "10.0.1.1"
|
||||
local_subnet_mask = "255.255.255.0"
|
||||
}
|
||||
|
||||
local_subnets {
|
||||
local_subnet_name = "WEB_EAST"
|
||||
local_subnet_gateway = "10.0.22.1"
|
||||
local_subnet_mask = "255.255.255.0"
|
||||
}
|
||||
}
|
||||
`
|
|
@ -0,0 +1,88 @@
|
|||
---
|
||||
layout: "vcd"
|
||||
page_title: "vCloudDirector: vcd_edgegateway_vpn"
|
||||
sidebar_current: "docs-vcd-resource-edgegateway-vpn"
|
||||
description: |-
|
||||
Provides a vCloud Director IPsec VPN. This can be used to create, modify, and delete VPN settings and rules.
|
||||
---
|
||||
|
||||
# vcd\_edgegateway\_vpn
|
||||
|
||||
Provides a vCloud Director IPsec VPN. This can be used to create,
|
||||
modify, and delete VPN settings and rules.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
resource "vcd_edgegateway_vpn" "vpn" {
|
||||
edge_gateway = "Internet_01(nti0000bi2_123-456-2)"
|
||||
name = "west-to-east"
|
||||
description = "Description"
|
||||
encryption_protocol = "AES256"
|
||||
mtu = 1400
|
||||
peer_id = "64.121.123.11"
|
||||
peer_ip_address = "64.121.123.11"
|
||||
local_id = "64.121.123.10"
|
||||
local_ip_address = "64.121.123.10"
|
||||
shared_secret = "***********************"
|
||||
|
||||
peer_subnets {
|
||||
peer_subnet_name = "DMZ_WEST"
|
||||
peer_subnet_gateway = "10.0.10.1"
|
||||
peer_subnet_mask = "255.255.255.0"
|
||||
}
|
||||
|
||||
peer_subnets {
|
||||
peer_subnet_name = "WEB_WEST"
|
||||
peer_subnet_gateway = "10.0.20.1"
|
||||
peer_subnet_mask = "255.255.255.0"
|
||||
}
|
||||
|
||||
local_subnets {
|
||||
local_subnet_name = "DMZ_EAST"
|
||||
local_subnet_gateway = "10.0.1.1"
|
||||
local_subnet_mask = "255.255.255.0"
|
||||
}
|
||||
|
||||
local_subnets {
|
||||
local_subnet_name = "WEB_EAST"
|
||||
local_subnet_gateway = "10.0.22.1"
|
||||
local_subnet_mask = "255.255.255.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `edge_gateway` - (Required) The name of the edge gateway on which to apply the Firewall Rules
|
||||
* `name` - (Required) The name of the VPN
|
||||
* `description` - (Required) A description for the VPN
|
||||
* `encryption_protocol` - (Required) - E.g. `AES256`
|
||||
* `local_ip_address` - (Required) - Local IP Address
|
||||
* `local_id` - (Required) - Local ID
|
||||
* `mtu` - (Required) - The MTU setting
|
||||
* `peer_ip_address` - (Required) - Peer IP Address
|
||||
* `peer_id` - (Required) - Peer ID
|
||||
* `shared_secret` - (Required) - Shared Secret
|
||||
* `local_subnets` - (Required) - List of Local Subnets see [Local Subnets](#localsubnets) below for details.
|
||||
* `peer_subnets` - (Required) - List of Peer Subnets see [Peer Subnets](#peersubnets) below for details.
|
||||
|
||||
<a id="localsubnets"></a>
|
||||
## Local Subnets
|
||||
|
||||
Each Local Subnet supports the following attributes:
|
||||
|
||||
* `local_subnet_name` - (Required) Name of the local subnet
|
||||
* `local_subnet_gateway` - (Required) Gateway of the local subnet
|
||||
* `local_subnet_mask` - (Required) Subnet mask of the local subnet
|
||||
|
||||
<a id="peersubnets"></a>
|
||||
## Peer Subnets
|
||||
|
||||
Each Peer Subnet supports the following attributes:
|
||||
|
||||
* `peer_subnet_name` - (Required) Name of the peer subnet
|
||||
* `peer_subnet_gateway` - (Required) Gateway of the peer subnet
|
||||
* `peer_subnet_mask` - (Required) Subnet mask of the peer subnet
|
Loading…
Reference in New Issue