diff --git a/azurerm/resource_arm_api_management.go b/azurerm/resource_arm_api_management.go index 64eccaa010bb..e3e60489610e 100644 --- a/azurerm/resource_arm_api_management.go +++ b/azurerm/resource_arm_api_management.go @@ -53,6 +53,14 @@ func resourceArmApiManagementService() *schema.Resource { }, }, + "private_ip_addresses": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "publisher_name": { Type: schema.TypeString, Required: true, @@ -124,11 +132,18 @@ func resourceArmApiManagementService() *schema.Resource { "additional_location": { Type: schema.TypeList, Optional: true, - MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "location": locationSchema(), + "virtual_network_configuration": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: apiManagementResourceVirtualNetworkConfigurationSchema(), + }, + }, + "gateway_regional_url": { Type: schema.TypeString, Computed: true, @@ -141,6 +156,14 @@ func resourceArmApiManagementService() *schema.Resource { }, Computed: true, }, + + "private_ip_addresses": { + Type: schema.TypeList, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Computed: true, + }, }, }, }, @@ -260,6 +283,32 @@ func resourceArmApiManagementService() *schema.Resource { }, }, + "virtual_network_type": { + Type: schema.TypeString, + Optional: true, + Default: string(apimanagement.VirtualNetworkTypeNone), + ValidateFunc: validation.StringInSlice([]string{ + string(apimanagement.VirtualNetworkTypeInternal), + string(apimanagement.VirtualNetworkTypeExternal), + string(apimanagement.VirtualNetworkTypeNone), + }, 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, + ValidateFunc: azure.ValidateResourceID, + }, + }, + }, + }, + "tags": tagsSchema(), "gateway_url": { @@ -342,6 +391,14 @@ func resourceArmApiManagementServiceCreateUpdate(d *schema.ResourceData, meta in properties.Identity = expandAzureRmApiManagementIdentity(d) } + if _, ok := d.GetOk("virtual_network_type"); ok { + properties.ServiceProperties.VirtualNetworkType = apimanagement.VirtualNetworkType(d.Get("virtual_network_type").(string)) + } + + if _, ok := d.GetOk("virtual_network_configuration"); ok { + properties.ServiceProperties.VirtualNetworkConfiguration = expandAzureRmApiManagementVirtualNetworkConfiguration(d) + } + if _, ok := d.GetOk("additional_location"); ok { properties.ServiceProperties.AdditionalLocations = expandAzureRmApiManagementAdditionalLocations(d, sku) } @@ -418,6 +475,7 @@ 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) if err := d.Set("security", flattenApiManagementCustomProperties(props.CustomProperties)); err != nil { return fmt.Errorf("Error setting `security`: %+v", err) @@ -428,6 +486,12 @@ func resourceArmApiManagementServiceRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("Error setting `hostname_configuration`: %+v", err) } + d.Set("virtual_network_type", props.VirtualNetworkType) + + if err := d.Set("virtual_network_configuration", flattenApiManagementVirtualNetworkConfiguration(props.VirtualNetworkConfiguration)); err != nil { + return fmt.Errorf("Error setting `virtual_network_configuration`: %+v", err) + } + if err := d.Set("additional_location", flattenApiManagementAdditionalLocations(props.AdditionalLocations)); err != nil { return fmt.Errorf("Error setting `additional_location`: %+v", err) } @@ -640,6 +704,10 @@ func expandAzureRmApiManagementAdditionalLocations(d *schema.ResourceData, sku * Sku: sku, } + if _, ok := config["virtual_network_configuration"]; ok { + additionalLocation.VirtualNetworkConfiguration = expandApiManagementVirtualNetworkConfiguration(config) + } + additionalLocations = append(additionalLocations, additionalLocation) } @@ -659,10 +727,18 @@ func flattenApiManagementAdditionalLocations(input *[]apimanagement.AdditionalLo output["location"] = azureRMNormalizeLocation(*prop.Location) } + if prop.VirtualNetworkConfiguration != nil { + output["virtual_network_configuration"] = flattenApiManagementVirtualNetworkConfiguration(prop.VirtualNetworkConfiguration) + } + if prop.PublicIPAddresses != nil { output["public_ip_addresses"] = *prop.PublicIPAddresses } + if prop.PrivateIPAddresses != nil { + output["private_ip_addresses"] = *prop.PrivateIPAddresses + } + if prop.GatewayRegionalURL != nil { output["gateway_regional_url"] = *prop.GatewayRegionalURL } @@ -740,6 +816,51 @@ func flattenApiManagementServiceSku(input *apimanagement.ServiceSkuProperties) [ return []interface{}{sku} } +func expandAzureRmApiManagementVirtualNetworkConfiguration(d *schema.ResourceData) *apimanagement.VirtualNetworkConfiguration { + vs := d.Get("virtual_network_configuration").([]interface{}) + // guaranteed by MinItems in the schema + v := vs[0].(map[string]interface{}) + + subnetid := v["subnet_id"].(string) + + vnetConfig := &apimanagement.VirtualNetworkConfiguration{ + SubnetResourceID: utils.String(subnetid), + } + + return vnetConfig +} + +func expandApiManagementVirtualNetworkConfiguration(input map[string]interface{}) *apimanagement.VirtualNetworkConfiguration { + vs := input["virtual_network_configuration"].([]interface{}) + + if len(vs) == 0 { + return nil + } + v := vs[0].(map[string]interface{}) + + subnetid := v["subnet_id"].(string) + + vnetConfig := &apimanagement.VirtualNetworkConfiguration{ + SubnetResourceID: utils.String(subnetid), + } + + return vnetConfig +} + +func flattenApiManagementVirtualNetworkConfiguration(input *apimanagement.VirtualNetworkConfiguration) []interface{} { + if input == nil { + return []interface{}{} + } + + vnetConfig := make(map[string]interface{}) + + if id := input.SubnetResourceID; id != nil { + vnetConfig["subnet_id"] = *id + } + + return []interface{}{vnetConfig} +} + func expandApiManagementCustomProperties(d *schema.ResourceData) map[string]*string { vs := d.Get("security").([]interface{}) @@ -845,6 +966,16 @@ func apiManagementResourceHostnameProxySchema() map[string]*schema.Schema { return hostnameSchema } +func apiManagementResourceVirtualNetworkConfigurationSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "subnet_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + } +} + func parseApiManagementNilableDictionary(input map[string]*string, key string) bool { log.Printf("Parsing value for %q", key) diff --git a/azurerm/resource_arm_api_management_test.go b/azurerm/resource_arm_api_management_test.go index 390b00a7c078..283ddd64e06d 100755 --- a/azurerm/resource_arm_api_management_test.go +++ b/azurerm/resource_arm_api_management_test.go @@ -262,6 +262,34 @@ resource "azurerm_resource_group" "test2" { location = "%s" } +resource "azurerm_virtual_network" "test1" { + name = "acctest-vnet-%d" + resource_group_name = "${azurerm_resource_group.test1.name}" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.test1.location}" +} + +resource "azurerm_subnet" "test1" { + name = "subnet-%d" + resource_group_name = "${azurerm_resource_group.test1.name}" + virtual_network_name = "${azurerm_virtual_network.test1.name}" + address_prefix = "10.0.0.0/24" +} + +resource "azurerm_virtual_network" "test2" { + name = "acctest-vnet-%d" + resource_group_name = "${azurerm_resource_group.test2.name}" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.test2.location}" +} + +resource "azurerm_subnet" "test2" { + name = "subnet-%d" + resource_group_name = "${azurerm_resource_group.test2.name}" + virtual_network_name = "${azurerm_virtual_network.test2.name}" + address_prefix = "10.0.0.0/24" +} + resource "azurerm_api_management" "test" { name = "acctestAM-%d" publisher_name = "pub1" @@ -269,7 +297,11 @@ resource "azurerm_api_management" "test" { notification_sender_email = "notification@email.com" additional_location { - location = "${azurerm_resource_group.test2.location}" + location = "${azurerm_resource_group.test2.location}" + + virtual_network_configuration { + subnet_id = "${azurerm_subnet.test2.id}" + } } certificate { @@ -309,7 +341,13 @@ resource "azurerm_api_management" "test" { certificate = "${base64encode(file("testdata/api_management_portal_test.pfx"))}" certificate_password = "terraform" } - } + } + + virtual_network_type = "External" + + virtual_network_configuration { + subnet_id = "${azurerm_subnet.test1.id}" + } sku { name = "Premium" @@ -323,5 +361,5 @@ resource "azurerm_api_management" "test" { location = "${azurerm_resource_group.test1.location}" resource_group_name = "${azurerm_resource_group.test1.name}" } -`, rInt, location, rInt, altLocation, rInt) +`, rInt, location, rInt, altLocation, rInt, rInt, rInt, rInt, rInt) } diff --git a/website/docs/r/api_management.html.markdown b/website/docs/r/api_management.html.markdown index be6f2b5cd59f..6311a54d9f85 100755 --- a/website/docs/r/api_management.html.markdown +++ b/website/docs/r/api_management.html.markdown @@ -62,6 +62,10 @@ The following arguments are supported: * `security` - (Optional) A `security` block as defined below. +* `virtual_network_type` - (Optional) Specifies the Virtual Network Integration for the API Management Service. Possible values include: `None`, `External`, and `Internal`. + +* `virtual_network_configuration` - (Optional) A `virtual_network_configuration` block as defined below. + * `tags` - (Optional) A mapping of tags assigned to the resource. --- @@ -70,6 +74,8 @@ A `additional_location` block supports the following: * `location` - (Required) The name of the Azure Region in which the API Management Service should be expanded to. +* `virtual_network_configuration` - (Optional) A `virtual_network_configuration` block as defined below. Required when `virtual_network_type` is `External` or `Internal` + --- A `certificate` block supports the following: @@ -120,6 +126,12 @@ A `security` block supports the following: --- +A `virtual_network_configuration` block supports the following: + +* `subnet_id` - (Required) Specifies the resource id of the subnet to integrate the API management service with. + +--- + A `sku` block supports the following: * `name` - (Required) Specifies the Pricing Tier for the API Management Service. Possible values include: `Developer`, `Basic`, `Standard` and `Premium`. @@ -194,6 +206,8 @@ In addition to all arguments above, the following attributes are exported: * `public_ip_addresses` - The Public IP addresses of the API Management Service. +* `private_ip_addresses` - The Private IP addresses of the API Management Service if integrated in the Virtual Network. + * `scm_url` - The URL for the SCM (Source Code Management) Endpoint associated with this API Management service. * `identity` - An `identity` block as defined below. @@ -216,6 +230,8 @@ An `additional_location` block exports the following: * `public_ip_addresses` - Public Static Load Balanced IP addresses of the API Management service in the additional location. Available only for Basic, Standard and Premium SKU. +* `private_ip_addresses` - Private Static Load Balanced IP addresses of the API Management service in the virtual network of the additional locations. Available only for Basic, Standard and Premium SKU. + ## Import API Management Services can be imported using the `resource id`, e.g.