From e67f141561d662fd557d0c8f0904e7fc03052340 Mon Sep 17 00:00:00 2001 From: Peter McAtominey Date: Sat, 13 Aug 2016 19:37:46 +0100 Subject: [PATCH] provider/azurerm: create virtual_network_peering resource (#8168) TF_ACC=1 go test ./builtin/providers/azurerm -v -run TestAccAzureRMVirtualNetworkPeering -timeout 120m === RUN TestAccAzureRMVirtualNetworkPeering_importBasic --- PASS: TestAccAzureRMVirtualNetworkPeering_importBasic (225.50s) === RUN TestAccAzureRMVirtualNetworkPeering_basic --- PASS: TestAccAzureRMVirtualNetworkPeering_basic (216.95s) === RUN TestAccAzureRMVirtualNetworkPeering_update --- PASS: TestAccAzureRMVirtualNetworkPeering_update (266.97s) PASS ok github.com/hashicorp/terraform/builtin/providers/azurerm 709.545s --- builtin/providers/azurerm/config.go | 7 + ...import_arm_virtual_network_peering_test.go | 34 +++ builtin/providers/azurerm/provider.go | 1 + .../resource_arm_virtual_network_peering.go | 182 +++++++++++++++ ...source_arm_virtual_network_peering_test.go | 212 ++++++++++++++++++ .../r/virtual_network_peering.html.markdown | 102 +++++++++ website/source/layouts/azurerm.erb | 4 + 7 files changed, 542 insertions(+) create mode 100644 builtin/providers/azurerm/import_arm_virtual_network_peering_test.go create mode 100644 builtin/providers/azurerm/resource_arm_virtual_network_peering.go create mode 100644 builtin/providers/azurerm/resource_arm_virtual_network_peering_test.go create mode 100644 website/source/docs/providers/azurerm/r/virtual_network_peering.html.markdown diff --git a/builtin/providers/azurerm/config.go b/builtin/providers/azurerm/config.go index b85166d76..04d6403c8 100644 --- a/builtin/providers/azurerm/config.go +++ b/builtin/providers/azurerm/config.go @@ -45,6 +45,7 @@ type ArmClient struct { vnetGatewayConnectionsClient network.VirtualNetworkGatewayConnectionsClient vnetGatewayClient network.VirtualNetworkGatewaysClient vnetClient network.VirtualNetworksClient + vnetPeeringsClient network.VirtualNetworkPeeringsClient routeTablesClient network.RouteTablesClient routesClient network.RoutesClient @@ -257,6 +258,12 @@ func (c *Config) getArmClient() (*ArmClient, error) { vnc.Sender = autorest.CreateSender(withRequestLogging()) client.vnetClient = vnc + vnpc := network.NewVirtualNetworkPeeringsClient(c.SubscriptionID) + setUserAgent(&vnpc.Client) + vnpc.Authorizer = spt + vnpc.Sender = autorest.CreateSender(withRequestLogging()) + client.vnetPeeringsClient = vnpc + rtc := network.NewRouteTablesClient(c.SubscriptionID) setUserAgent(&rtc.Client) rtc.Authorizer = spt diff --git a/builtin/providers/azurerm/import_arm_virtual_network_peering_test.go b/builtin/providers/azurerm/import_arm_virtual_network_peering_test.go new file mode 100644 index 000000000..8269294f8 --- /dev/null +++ b/builtin/providers/azurerm/import_arm_virtual_network_peering_test.go @@ -0,0 +1,34 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccAzureRMVirtualNetworkPeering_importBasic(t *testing.T) { + resourceName := "azurerm_virtual_network_peering.test1" + + ri := acctest.RandInt() + config := fmt.Sprintf(testAccAzureRMVirtualNetworkPeering_basic, ri, ri, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMVirtualNetworkPeeringDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: config, + }, + + resource.TestStep{ + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"resource_group_name"}, + }, + }, + }) +} diff --git a/builtin/providers/azurerm/provider.go b/builtin/providers/azurerm/provider.go index dd85e7bfb..e235fe7a6 100644 --- a/builtin/providers/azurerm/provider.go +++ b/builtin/providers/azurerm/provider.go @@ -68,6 +68,7 @@ func Provider() terraform.ResourceProvider { "azurerm_virtual_machine": resourceArmVirtualMachine(), "azurerm_virtual_machine_scale_set": resourceArmVirtualMachineScaleSet(), "azurerm_virtual_network": resourceArmVirtualNetwork(), + "azurerm_virtual_network_peering": resourceArmVirtualNetworkPeering(), // These resources use the Riviera SDK "azurerm_dns_a_record": resourceArmDnsARecord(), diff --git a/builtin/providers/azurerm/resource_arm_virtual_network_peering.go b/builtin/providers/azurerm/resource_arm_virtual_network_peering.go new file mode 100644 index 000000000..854ceeae0 --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_virtual_network_peering.go @@ -0,0 +1,182 @@ +package azurerm + +import ( + "fmt" + "log" + "net/http" + "sync" + + "github.com/Azure/azure-sdk-for-go/arm/network" + "github.com/hashicorp/terraform/helper/schema" +) + +// peerMutex is used to prevet multiple Peering resources being creaed, updated +// or deleted at the same time +var peerMutex = &sync.Mutex{} + +func resourceArmVirtualNetworkPeering() *schema.Resource { + return &schema.Resource{ + Create: resourceArmVirtualNetworkPeeringCreate, + Read: resourceArmVirtualNetworkPeeringRead, + Update: resourceArmVirtualNetworkPeeringCreate, + Delete: resourceArmVirtualNetworkPeeringDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "resource_group_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "virtual_network_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "remote_virtual_network_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "allow_virtual_network_access": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + + "allow_forwarded_traffic": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + + "allow_gateway_transit": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + + "use_remote_gateways": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + }, + } +} + +func resourceArmVirtualNetworkPeeringCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).vnetPeeringsClient + + log.Printf("[INFO] preparing arguments for Azure ARM virtual network peering creation.") + + name := d.Get("name").(string) + vnetName := d.Get("virtual_network_name").(string) + resGroup := d.Get("resource_group_name").(string) + + peer := network.VirtualNetworkPeering{ + Name: &name, + Properties: getVirtualNetworkPeeringProperties(d), + } + + peerMutex.Lock() + defer peerMutex.Unlock() + + _, err := client.CreateOrUpdate(resGroup, vnetName, name, peer, make(chan struct{})) + if err != nil { + return err + } + + read, err := client.Get(resGroup, vnetName, name) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Cannot read Virtual Network Peering %s (resource group %s) ID", name, resGroup) + } + + d.SetId(*read.ID) + + return resourceArmVirtualNetworkPeeringRead(d, meta) +} + +func resourceArmVirtualNetworkPeeringRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).vnetPeeringsClient + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resGroup := id.ResourceGroup + vnetName := id.Path["virtualNetworks"] + name := id.Path["virtualNetworkPeerings"] + + resp, err := client.Get(resGroup, vnetName, name) + if resp.StatusCode == http.StatusNotFound { + d.SetId("") + return nil + } + if err != nil { + return fmt.Errorf("Error making Read request on Azure virtual network peering %s: %s", name, err) + } + peer := *resp.Properties + + // update appropriate values + d.Set("name", resp.Name) + d.Set("virtual_network_name", vnetName) + d.Set("allow_virtual_network_access", peer.AllowVirtualNetworkAccess) + d.Set("allow_forwarded_traffic", peer.AllowForwardedTraffic) + d.Set("allow_gateway_transit", peer.AllowGatewayTransit) + d.Set("use_remote_gateways", peer.UseRemoteGateways) + d.Set("remote_virtual_network_id", peer.RemoteVirtualNetwork.ID) + + return nil +} + +func resourceArmVirtualNetworkPeeringDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).vnetPeeringsClient + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resGroup := id.ResourceGroup + vnetName := id.Path["virtualNetworks"] + name := id.Path["virtualNetworkPeerings"] + + peerMutex.Lock() + defer peerMutex.Unlock() + + _, err = client.Delete(resGroup, vnetName, name, make(chan struct{})) + + return err +} + +func getVirtualNetworkPeeringProperties(d *schema.ResourceData) *network.VirtualNetworkPeeringPropertiesFormat { + allowVirtualNetworkAccess := d.Get("allow_virtual_network_access").(bool) + allowForwardedTraffic := d.Get("allow_forwarded_traffic").(bool) + allowGatewayTransit := d.Get("allow_gateway_transit").(bool) + useRemoteGateways := d.Get("use_remote_gateways").(bool) + remoteVirtualNetworkID := d.Get("remote_virtual_network_id").(string) + + return &network.VirtualNetworkPeeringPropertiesFormat{ + AllowVirtualNetworkAccess: &allowVirtualNetworkAccess, + AllowForwardedTraffic: &allowForwardedTraffic, + AllowGatewayTransit: &allowGatewayTransit, + UseRemoteGateways: &useRemoteGateways, + RemoteVirtualNetwork: &network.SubResource{ + ID: &remoteVirtualNetworkID, + }, + } +} diff --git a/builtin/providers/azurerm/resource_arm_virtual_network_peering_test.go b/builtin/providers/azurerm/resource_arm_virtual_network_peering_test.go new file mode 100644 index 000000000..08a48ecd7 --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_virtual_network_peering_test.go @@ -0,0 +1,212 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/core/http" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAzureRMVirtualNetworkPeering_basic(t *testing.T) { + ri := acctest.RandInt() + config := fmt.Sprintf(testAccAzureRMVirtualNetworkPeering_basic, ri, ri, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMVirtualNetworkPeeringDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMVirtualNetworkPeeringExists("azurerm_virtual_network_peering.test1"), + testCheckAzureRMVirtualNetworkPeeringExists("azurerm_virtual_network_peering.test2"), + resource.TestCheckResourceAttr( + "azurerm_virtual_network_peering.test1", "allow_virtual_network_access", "true"), + resource.TestCheckResourceAttr( + "azurerm_virtual_network_peering.test2", "allow_virtual_network_access", "true"), + ), + }, + }, + }) +} + +func TestAccAzureRMVirtualNetworkPeering_update(t *testing.T) { + ri := acctest.RandInt() + preConfig := fmt.Sprintf(testAccAzureRMVirtualNetworkPeering_basic, ri, ri, ri, ri, ri) + postConfig := fmt.Sprintf(testAccAzureRMVirtualNetworkPeering_basicUpdate, ri, ri, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMVirtualNetworkPeeringDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMVirtualNetworkPeeringExists("azurerm_virtual_network_peering.test1"), + testCheckAzureRMVirtualNetworkPeeringExists("azurerm_virtual_network_peering.test2"), + resource.TestCheckResourceAttr( + "azurerm_virtual_network_peering.test1", "allow_virtual_network_access", "true"), + resource.TestCheckResourceAttr( + "azurerm_virtual_network_peering.test2", "allow_virtual_network_access", "true"), + resource.TestCheckResourceAttr( + "azurerm_virtual_network_peering.test1", "allow_forwarded_traffic", "false"), + resource.TestCheckResourceAttr( + "azurerm_virtual_network_peering.test2", "allow_forwarded_traffic", "false"), + ), + }, + + resource.TestStep{ + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMVirtualNetworkPeeringExists("azurerm_virtual_network_peering.test1"), + testCheckAzureRMVirtualNetworkPeeringExists("azurerm_virtual_network_peering.test2"), + resource.TestCheckResourceAttr( + "azurerm_virtual_network_peering.test1", "allow_virtual_network_access", "true"), + resource.TestCheckResourceAttr( + "azurerm_virtual_network_peering.test2", "allow_virtual_network_access", "true"), + resource.TestCheckResourceAttr( + "azurerm_virtual_network_peering.test1", "allow_forwarded_traffic", "true"), + resource.TestCheckResourceAttr( + "azurerm_virtual_network_peering.test2", "allow_forwarded_traffic", "true"), + ), + }, + }, + }) +} + +func testCheckAzureRMVirtualNetworkPeeringExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + name := rs.Primary.Attributes["name"] + vnetName := rs.Primary.Attributes["virtual_network_name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for virtual network peering: %s", name) + } + + // Ensure resource group/virtual network peering combination exists in API + conn := testAccProvider.Meta().(*ArmClient).vnetPeeringsClient + + resp, err := conn.Get(resourceGroup, vnetName, name) + if err != nil { + return fmt.Errorf("Bad: Get on vnetPeeringsClient: %s", err) + } + + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: Virtual Network Peering %q (resource group: %q) does not exist", name, resourceGroup) + } + + return nil + } +} + +func testCheckAzureRMVirtualNetworkPeeringDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).vnetPeeringsClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_virtual_network_peering" { + continue + } + + name := rs.Primary.Attributes["name"] + vnetName := rs.Primary.Attributes["virtual_network_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := conn.Get(resourceGroup, vnetName, name) + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("Virtual Network Peering sitll exists:\n%#v", resp.Properties) + } + } + + return nil +} + +var testAccAzureRMVirtualNetworkPeering_basic = ` +resource "azurerm_resource_group" "test" { + name = "acctestrg-%d" + location = "West US" +} + +resource "azurerm_virtual_network" "test1" { + name = "acctestvirtnet-1-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + address_space = ["10.0.1.0/24"] + location = "${azurerm_resource_group.test.location}" +} + +resource "azurerm_virtual_network" "test2" { + name = "acctestvirtnet-2-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + address_space = ["10.0.2.0/24"] + location = "${azurerm_resource_group.test.location}" +} + +resource "azurerm_virtual_network_peering" "test1" { + name = "acctestpeer-1-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test1.name}" + remote_virtual_network_id = "${azurerm_virtual_network.test2.id}" + allow_virtual_network_access = true +} + +resource "azurerm_virtual_network_peering" "test2" { + name = "acctestpeer-2-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test2.name}" + remote_virtual_network_id = "${azurerm_virtual_network.test1.id}" + allow_virtual_network_access = true +} +` + +var testAccAzureRMVirtualNetworkPeering_basicUpdate = ` +resource "azurerm_resource_group" "test" { + name = "acctestrg-%d" + location = "West US" +} + +resource "azurerm_virtual_network" "test1" { + name = "acctestvirtnet-1-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + address_space = ["10.0.1.0/24"] + location = "${azurerm_resource_group.test.location}" +} + +resource "azurerm_virtual_network" "test2" { + name = "acctestvirtnet-2-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + address_space = ["10.0.2.0/24"] + location = "${azurerm_resource_group.test.location}" +} + +resource "azurerm_virtual_network_peering" "test1" { + name = "acctestpeer-1-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test1.name}" + remote_virtual_network_id = "${azurerm_virtual_network.test2.id}" + allow_forwarded_traffic = true + allow_virtual_network_access = true +} + +resource "azurerm_virtual_network_peering" "test2" { + name = "acctestpeer-2-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test2.name}" + remote_virtual_network_id = "${azurerm_virtual_network.test1.id}" + allow_forwarded_traffic = true + allow_virtual_network_access = true +} +` diff --git a/website/source/docs/providers/azurerm/r/virtual_network_peering.html.markdown b/website/source/docs/providers/azurerm/r/virtual_network_peering.html.markdown new file mode 100644 index 000000000..fd635c4ee --- /dev/null +++ b/website/source/docs/providers/azurerm/r/virtual_network_peering.html.markdown @@ -0,0 +1,102 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azure_virtual_network_peering" +sidebar_current: "docs-azurerm-resource-network-virtual-network-peering" +description: |- + Creates a new virtual network peering which allows resources to access other + resources in the linked virtual network. +--- + +# azurerm\_virtual\_network\_peering + +Creates a new virtual network peering which allows resources to access other +resources in the linked virtual network. + +## Example Usage + +``` +resource "azurerm_resource_group" "test" { + name = "peeredvnets-rg" + location = "West US" +} + +resource "azurerm_virtual_network" "test1" { + name = "peternetwork1" + resource_group_name = "${azurerm_resource_group.test.name}" + address_space = ["10.0.1.0/24"] + location = "West US" +} + +resource "azurerm_virtual_network" "test2" { + name = "peternetwork2" + resource_group_name = "${azurerm_resource_group.test.name}" + address_space = ["10.0.2.0/24"] + location = "West US" +} + +resource "azurerm_virtual_network_peering" "test1" { + name = "peer1to2" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test1.name}" + remote_virtual_network_id = "${azurerm_virtual_network.test2.id}" +} + +resource "azurerm_virtual_network_peering" "test2" { + name = "peer2to1" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test2.name}" + remote_virtual_network_id = "${azurerm_virtual_network.test1.id}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the virtual network peering. Changing this + forces a new resource to be created. + +* `virtual_network_name` - (Required) The name of the virtual network. Changing + this forces a new resource to be created. + +* `remote_virtual_network_id` - (Required) The full Azure resource ID of the + remote virtual network. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the resource group in which to + create the virtual network. Changing this forces a new resource to be + created. + +* `allow_virtual_network_access` - (Optional) Controls if the VMs in the remote + virtual network can access VMs in the local virtual network. Defaults to + false. + +* `allow_forwarded_traffic` - (Optional) Controls if forwarded traffic from VMs + in the remote virtual network is allowed. Defaults to false. + +* `allow_gateway_transit` - (Optional) Controls gatewayLinks can be used in the + remote virtual network’s link to the local virtual network. + +* `use_remote_gateways` - (Optional) Controls if remote gateways can be used on + the local virtual network. If the flag is set to true, and + allowGatewayTransit on the remote peering is also true, virtual network will + use gateways of remote virtual network for transit. Only one peering can + have this flag set to true. This flag cannot be set if virtual network + already has a gateway. Defaults to false. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Virtual Network Peering resource ID. + +## Note + +Virtual Network peerings cannot be created, updated or deleted concurrently. + +## Import + +Virtual Network Peerings can be imported using the `resource id`, e.g. + +``` +terraform import azurerm_virtual_network_peering.testPeering /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Network/virtualNetworks/myvnet1/virtualNetworkPeerings/myvnet1peering +``` \ No newline at end of file diff --git a/website/source/layouts/azurerm.erb b/website/source/layouts/azurerm.erb index df3bcea46..b617310bb 100644 --- a/website/source/layouts/azurerm.erb +++ b/website/source/layouts/azurerm.erb @@ -82,6 +82,10 @@ azurerm_virtual_network + > + azurerm_virtual_network_peering + + > azurerm_network_security_group