Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_api_management - support for virtual network integration #5769

Merged
Expand Up @@ -64,6 +64,14 @@ func resourceArmApiManagementService() *schema.Resource {
},
},

"private_ip_addresses": {
Copy link
Collaborator

@katbyte katbyte Apr 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We typically group computed properties at the bottom of the schema, ie required -> optional -> computes

Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},

"publisher_name": {
Type: schema.TypeString,
Required: true,
Expand Down Expand Up @@ -112,6 +120,33 @@ func resourceArmApiManagementService() *schema.Resource {
},
},

"virtual_network_type": {
Type: schema.TypeString,
Optional: true,
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,
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we validate this is a proper id with azure.ValidateResourceID

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

},
},
},

"notification_sender_email": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -414,6 +449,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 +480,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 +618,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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This property doesn't exist?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we add it to the schema

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

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 +637,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 +996,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 +1032,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" {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we'll need a provider block here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

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