Skip to content

Commit

Permalink
azurerm_api_management - support for virtual network integrati… (#5769)
Browse files Browse the repository at this point in the history
The PR adds API Management virtual network integration both internal and external.

Fixes #3667
  • Loading branch information
francescopersico committed Apr 23, 2020
1 parent a9af902 commit 8b8adca
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 13 deletions.
109 changes: 96 additions & 13 deletions azurerm/internal/services/apimanagement/resource_arm_api_management.go
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
},
Expand All @@ -379,6 +413,8 @@ func resourceArmApiManagementService() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},

"tags": tags.Schema(),
},
}
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -444,6 +481,18 @@ func resourceArmApiManagementServiceCreateUpdate(d *schema.ResourceData, meta in
properties.ServiceProperties.NotificationSenderEmail = &notificationSenderEmail
}

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)
Expand Down Expand Up @@ -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)
Expand All @@ -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 {
Expand Down Expand Up @@ -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{})

Expand All @@ -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": {
Expand Down
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
10 changes: 10 additions & 0 deletions website/docs/r/api_management.html.markdown
Expand Up @@ -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.

---
Expand Down Expand Up @@ -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?
Expand Down

0 comments on commit 8b8adca

Please sign in to comment.