From 8b8adca1d7626845e21ec9e3edd4ee9919c96ea9 Mon Sep 17 00:00:00 2001 From: Francesco Persico Date: Thu, 23 Apr 2020 23:51:55 +0200 Subject: [PATCH] =?UTF-8?q?azurerm=5Fapi=5Fmanagement=20-=20support=20for?= =?UTF-8?q?=20=20virtual=20network=20integrati=E2=80=A6=20(#5769)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PR adds API Management virtual network integration both internal and external. Fixes #3667 --- .../resource_arm_api_management.go | 109 +++++++++++++++--- .../tests/resource_arm_api_management_test.go | 62 ++++++++++ website/docs/r/api_management.html.markdown | 10 ++ 3 files changed, 168 insertions(+), 13 deletions(-) diff --git a/azurerm/internal/services/apimanagement/resource_arm_api_management.go b/azurerm/internal/services/apimanagement/resource_arm_api_management.go index f52e5682ee56..8beb983b5f2f 100644 --- a/azurerm/internal/services/apimanagement/resource_arm_api_management.go +++ b/azurerm/internal/services/apimanagement/resource_arm_api_management.go @@ -56,14 +56,6 @@ func resourceArmApiManagementService() *schema.Resource { "location": azure.SchemaLocation(), - "public_ip_addresses": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "publisher_name": { Type: schema.TypeString, Required: true, @@ -112,6 +104,34 @@ func resourceArmApiManagementService() *schema.Resource { }, }, + "virtual_network_type": { + Type: schema.TypeString, + Optional: true, + Default: string(apimanagement.VirtualNetworkTypeNone), + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(apimanagement.VirtualNetworkTypeNone), + string(apimanagement.VirtualNetworkTypeExternal), + string(apimanagement.VirtualNetworkTypeInternal), + }, false), + }, + + "virtual_network_configuration": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "subnet_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateResourceID, + }, + }, + }, + }, + "notification_sender_email": { Type: schema.TypeString, Optional: true, @@ -353,24 +373,38 @@ func resourceArmApiManagementService() *schema.Resource { }, }, - "tags": tags.Schema(), - "gateway_url": { Type: schema.TypeString, Computed: true, }, - "gateway_regional_url": { + "management_api_url": { Type: schema.TypeString, Computed: true, }, - "portal_url": { + "gateway_regional_url": { Type: schema.TypeString, Computed: true, }, - "management_api_url": { + "public_ip_addresses": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "private_ip_addresses": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "portal_url": { Type: schema.TypeString, Computed: true, }, @@ -379,6 +413,8 @@ func resourceArmApiManagementService() *schema.Resource { Type: schema.TypeString, Computed: true, }, + + "tags": tags.Schema(), }, } } @@ -414,6 +450,7 @@ func resourceArmApiManagementServiceCreateUpdate(d *schema.ResourceData, meta in publisherName := d.Get("publisher_name").(string) publisherEmail := d.Get("publisher_email").(string) notificationSenderEmail := d.Get("notification_sender_email").(string) + virtualNetworkType := d.Get("virtual_network_type").(string) customProperties := expandApiManagementCustomProperties(d) certificates := expandAzureRmApiManagementCertificates(d) @@ -444,6 +481,18 @@ func resourceArmApiManagementServiceCreateUpdate(d *schema.ResourceData, meta in properties.ServiceProperties.NotificationSenderEmail = ¬ificationSenderEmail } + if virtualNetworkType != "" { + properties.ServiceProperties.VirtualNetworkType = apimanagement.VirtualNetworkType(virtualNetworkType) + + if virtualNetworkType != string(apimanagement.VirtualNetworkTypeNone) { + virtualNetworkConfiguration := expandAzureRmApiManagementVirtualNetworkConfigurations(d) + if virtualNetworkConfiguration == nil { + return fmt.Errorf("You must specify 'virtual_network_configuration' when 'virtual_network_type' is %q", virtualNetworkType) + } + properties.ServiceProperties.VirtualNetworkConfiguration = virtualNetworkConfiguration + } + } + future, err := client.CreateOrUpdate(ctx, resourceGroup, name, properties) if err != nil { return fmt.Errorf("creating/updating API Management Service %q (Resource Group %q): %+v", name, resourceGroup, err) @@ -570,6 +619,8 @@ func resourceArmApiManagementServiceRead(d *schema.ResourceData, meta interface{ d.Set("management_api_url", props.ManagementAPIURL) d.Set("scm_url", props.ScmURL) d.Set("public_ip_addresses", props.PublicIPAddresses) + d.Set("private_ip_addresses", props.PrivateIPAddresses) + d.Set("virtual_network_type", props.VirtualNetworkType) if err := d.Set("security", flattenApiManagementSecurityCustomProperties(props.CustomProperties)); err != nil { return fmt.Errorf("setting `security`: %+v", err) @@ -587,6 +638,10 @@ func resourceArmApiManagementServiceRead(d *schema.ResourceData, meta interface{ if err := d.Set("additional_location", flattenApiManagementAdditionalLocations(props.AdditionalLocations)); err != nil { return fmt.Errorf("setting `additional_location`: %+v", err) } + + if err := d.Set("virtual_network_configuration", flattenApiManagementVirtualNetworkConfiguration(props.VirtualNetworkConfiguration)); err != nil { + return fmt.Errorf("setting `virtual_network_configuration`: %+v", err) + } } if err := d.Set("sku_name", flattenApiManagementServiceSkuName(resp.Sku)); err != nil { @@ -942,6 +997,20 @@ func expandApiManagementCustomProperties(d *schema.ResourceData) map[string]*str return customProperties } +func expandAzureRmApiManagementVirtualNetworkConfigurations(d *schema.ResourceData) *apimanagement.VirtualNetworkConfiguration { + vs := d.Get("virtual_network_configuration").([]interface{}) + if len(vs) == 0 { + return nil + } + + v := vs[0].(map[string]interface{}) + subnetResourceId := v["subnet_id"].(string) + + return &apimanagement.VirtualNetworkConfiguration{ + SubnetResourceID: &subnetResourceId, + } +} + func flattenApiManagementSecurityCustomProperties(input map[string]*string) []interface{} { output := make(map[string]interface{}) @@ -964,6 +1033,20 @@ func flattenApiManagementProtocolsCustomProperties(input map[string]*string) []i return []interface{}{output} } +func flattenApiManagementVirtualNetworkConfiguration(input *apimanagement.VirtualNetworkConfiguration) []interface{} { + if input == nil { + return []interface{}{} + } + + virtualNetworkConfiguration := make(map[string]interface{}) + + if input.SubnetResourceID != nil { + virtualNetworkConfiguration["subnet_id"] = *input.SubnetResourceID + } + + return []interface{}{virtualNetworkConfiguration} +} + func apiManagementResourceHostnameSchema(schemaName string) map[string]*schema.Schema { return map[string]*schema.Schema{ "host_name": { diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_test.go index 2bb414ff7982..dca3bcafe011 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_test.go @@ -163,6 +163,26 @@ func TestAccAzureRMApiManagement_policy(t *testing.T) { }) } +func TestAccAzureRMApiManagement_virtualNetworkInternal(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_api_management", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMApiManagementDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApiManagement_virtualNetworkInternal(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "virtual_network_type", "Internal"), + ), + }, + data.ImportStep(), + }, + }) +} + func testCheckAzureRMApiManagementDestroy(s *terraform.State) error { conn := acceptance.AzureProvider.Meta().(*clients.Client).ApiManagement.ServiceClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext @@ -506,3 +526,45 @@ resource "azurerm_api_management" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.Locations.Secondary, data.RandomInteger, data.Locations.Ternary, data.RandomInteger) } + +func testAccAzureRMApiManagement_virtualNetworkInternal(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestVNET-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + address_space = ["10.0.0.0/16"] +} + +resource "azurerm_subnet" "test" { + name = "acctestSNET-%d" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.1.0/24" +} + +resource "azurerm_api_management" "test" { + name = "acctestAM-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + publisher_name = "pub1" + publisher_email = "pub1@email.com" + + sku_name = "Developer_1" + + virtual_network_type = "Internal" + virtual_network_configuration { + subnet_id = azurerm_subnet.test.id + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} diff --git a/website/docs/r/api_management.html.markdown b/website/docs/r/api_management.html.markdown index e4a863dec148..796b47c74638 100644 --- a/website/docs/r/api_management.html.markdown +++ b/website/docs/r/api_management.html.markdown @@ -79,6 +79,10 @@ The following arguments are supported: * `sign_up` - (Optional) A `sign_up` block as defined below. +* `virtual_network_type` - (Optional) The type of virtual network you want to use, valid values include: `None`, `External`, `Internal`. + +* `virtual_network_configuration` - (Optional) A `virtual_network_configuration` block as defined below. Required when `virtual_network_type` is `External` or `Internal`. + * `tags` - (Optional) A mapping of tags assigned to the resource. --- @@ -244,6 +248,12 @@ A `sign_up` block supports the following: --- +A `virtual_network_configuration` block supports the following: + +* `subnet_id` - (Required) The id of the subnet that will be used for the API Management. + +--- + A `terms_of_service` block supports the following: * `consent_required` - (Required) Should the user be asked for consent during sign up?