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 add sku_name Consumption_0 #6868

Merged
merged 10 commits into from
Dec 21, 2020
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 0 additions & 34 deletions azurerm/helpers/azure/sku.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import (
"fmt"
"strconv"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

func SplitSku(sku string) (string, int32, error) {
Expand All @@ -22,35 +20,3 @@ func SplitSku(sku string) (string, int32, error) {

return skuParts[0], int32(capacity), nil
}

// MinCapacitySkuNameInSlice returns a SchemaValidateFunc which tests if the provided value
// is of type string and matches the value of an element in the valid slice
// will test with in lower case if ignoreCase is true will also validate if the
// capacity if above passed minCapacity value
func MinCapacitySkuNameInSlice(valid []string, minCapacity int32, ignoreCase bool) schema.SchemaValidateFunc {
return func(i interface{}, k string) (s []string, es []error) {
v, ok := i.(string)
if !ok {
es = append(es, fmt.Errorf("expected type of %s to be string", k))
return
}

name, capacity, err := SplitSku(v)
if err != nil {
es = append(es, err)
return
}

for _, str := range valid {
if name == str || (ignoreCase && strings.EqualFold(name, str)) {
if capacity < minCapacity {
es = append(es, fmt.Errorf("expected %s capacity value to be greater that %d, got %d", k, minCapacity, capacity))
}
return
}
}

es = append(es, fmt.Errorf("expected %s to be one of %v, got %s", k, valid, name))
return
}
}
120 changes: 74 additions & 46 deletions azurerm/internal/services/apimanagement/api_management_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/apimanagement/parse"
apimValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/apimanagement/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
Expand Down Expand Up @@ -73,15 +74,10 @@ func resourceArmApiManagementService() *schema.Resource {
},

"sku_name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: azure.MinCapacitySkuNameInSlice([]string{
string(apimanagement.SkuTypeConsumption),
string(apimanagement.SkuTypeDeveloper),
string(apimanagement.SkuTypeBasic),
string(apimanagement.SkuTypeStandard),
string(apimanagement.SkuTypePremium),
}, 1, false),
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: apimValidate.ApimSkuName(),
},

"identity": {
Expand Down Expand Up @@ -518,7 +514,10 @@ func resourceArmApiManagementServiceCreateUpdate(d *schema.ResourceData, meta in
notificationSenderEmail := d.Get("notification_sender_email").(string)
virtualNetworkType := d.Get("virtual_network_type").(string)

customProperties := expandApiManagementCustomProperties(d)
customProperties, err := expandApiManagementCustomProperties(d, sku.Name == apimanagement.SkuTypeConsumption)
if err != nil {
return err
}
certificates := expandAzureRmApiManagementCertificates(d)

properties := apimanagement.ServiceResource{
Expand Down Expand Up @@ -590,17 +589,27 @@ func resourceArmApiManagementServiceCreateUpdate(d *schema.ResourceData, meta in
d.SetId(*read.ID)

signInSettingsRaw := d.Get("sign_in").([]interface{})
signInSettings := expandApiManagementSignInSettings(signInSettingsRaw)
signInClient := meta.(*clients.Client).ApiManagement.SignInClient
if _, err := signInClient.CreateOrUpdate(ctx, resourceGroup, name, signInSettings, ""); err != nil {
return fmt.Errorf(" setting Sign In settings for API Management Service %q (Resource Group %q): %+v", name, resourceGroup, err)
if sku.Name == apimanagement.SkuTypeConsumption && len(signInSettingsRaw) > 0 {
return fmt.Errorf("`sign_in` is not support for sku tier `Consumption`")
}
if sku.Name != apimanagement.SkuTypeConsumption {
signInSettings := expandApiManagementSignInSettings(signInSettingsRaw)
signInClient := meta.(*clients.Client).ApiManagement.SignInClient
if _, err := signInClient.CreateOrUpdate(ctx, resourceGroup, name, signInSettings, ""); err != nil {
return fmt.Errorf(" setting Sign In settings for API Management Service %q (Resource Group %q): %+v", name, resourceGroup, err)
}
yupwei68 marked this conversation as resolved.
Show resolved Hide resolved
}

signUpSettingsRaw := d.Get("sign_up").([]interface{})
signUpSettings := expandApiManagementSignUpSettings(signUpSettingsRaw)
signUpClient := meta.(*clients.Client).ApiManagement.SignUpClient
if _, err := signUpClient.CreateOrUpdate(ctx, resourceGroup, name, signUpSettings, ""); err != nil {
return fmt.Errorf(" setting Sign Up settings for API Management Service %q (Resource Group %q): %+v", name, resourceGroup, err)
if sku.Name == apimanagement.SkuTypeConsumption && len(signInSettingsRaw) > 0 {
return fmt.Errorf("`sign_up` is not support for sku tier `Consumption`")
}
if sku.Name != apimanagement.SkuTypeConsumption {
signUpSettings := expandApiManagementSignUpSettings(signUpSettingsRaw)
signUpClient := meta.(*clients.Client).ApiManagement.SignUpClient
if _, err := signUpClient.CreateOrUpdate(ctx, resourceGroup, name, signUpSettings, ""); err != nil {
return fmt.Errorf(" setting Sign Up settings for API Management Service %q (Resource Group %q): %+v", name, resourceGroup, err)
}
}
yupwei68 marked this conversation as resolved.
Show resolved Hide resolved

policyClient := meta.(*clients.Client).ApiManagement.PolicyClient
Expand Down Expand Up @@ -631,6 +640,8 @@ func resourceArmApiManagementServiceCreateUpdate(d *schema.ResourceData, meta in

func resourceArmApiManagementServiceRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).ApiManagement.ServiceClient
signInClient := meta.(*clients.Client).ApiManagement.SignInClient
signUpClient := meta.(*clients.Client).ApiManagement.SignUpClient
environment := meta.(*clients.Client).Account.Environment
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()
Expand All @@ -654,18 +665,6 @@ func resourceArmApiManagementServiceRead(d *schema.ResourceData, meta interface{
return fmt.Errorf("making Read request on API Management Service %q (Resource Group %q): %+v", name, resourceGroup, err)
}

signInClient := meta.(*clients.Client).ApiManagement.SignInClient
signInSettings, err := signInClient.Get(ctx, resourceGroup, name)
if err != nil {
return fmt.Errorf("retrieving Sign In Settings for API Management Service %q (Resource Group %q): %+v", name, resourceGroup, err)
}

signUpClient := meta.(*clients.Client).ApiManagement.SignUpClient
signUpSettings, err := signUpClient.Get(ctx, resourceGroup, name)
if err != nil {
return fmt.Errorf("retrieving Sign Up Settings for API Management Service %q (Resource Group %q): %+v", name, resourceGroup, err)
}

policyClient := meta.(*clients.Client).ApiManagement.PolicyClient
policy, err := policyClient.Get(ctx, resourceGroup, name, apimanagement.PolicyExportFormatXML)
if err != nil {
Expand Down Expand Up @@ -700,8 +699,10 @@ func resourceArmApiManagementServiceRead(d *schema.ResourceData, meta interface{
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)
if resp.Sku != nil && resp.Sku.Name != "" {
if err := d.Set("security", flattenApiManagementSecurityCustomProperties(props.CustomProperties, resp.Sku.Name == apimanagement.SkuTypeConsumption)); err != nil {
return fmt.Errorf("setting `security`: %+v", err)
}
}

if err := d.Set("protocols", flattenApiManagementProtocolsCustomProperties(props.CustomProperties)); err != nil {
Expand All @@ -727,16 +728,30 @@ func resourceArmApiManagementServiceRead(d *schema.ResourceData, meta interface{
return fmt.Errorf("setting `sku_name`: %+v", err)
}

if err := d.Set("sign_in", flattenApiManagementSignInSettings(signInSettings)); err != nil {
return fmt.Errorf("setting `sign_in`: %+v", err)
if err := d.Set("policy", flattenApiManagementPolicies(d, policy)); err != nil {
return fmt.Errorf("setting `policy`: %+v", err)
}

if err := d.Set("sign_up", flattenApiManagementSignUpSettings(signUpSettings)); err != nil {
return fmt.Errorf("setting `sign_up`: %+v", err)
}
if resp.Sku.Name != apimanagement.SkuTypeConsumption {
signInSettings, err := signInClient.Get(ctx, resourceGroup, name)
if err != nil {
return fmt.Errorf("retrieving Sign In Settings for API Management Service %q (Resource Group %q): %+v", name, resourceGroup, err)
}
if err := d.Set("sign_in", flattenApiManagementSignInSettings(signInSettings)); err != nil {
return fmt.Errorf("setting `sign_in`: %+v", err)
}

if err := d.Set("policy", flattenApiManagementPolicies(d, policy)); err != nil {
return fmt.Errorf("setting `policy`: %+v", err)
signUpSettings, err := signUpClient.Get(ctx, resourceGroup, name)
if err != nil {
return fmt.Errorf("retrieving Sign Up Settings for API Management Service %q (Resource Group %q): %+v", name, resourceGroup, err)
}

if err := d.Set("sign_up", flattenApiManagementSignUpSettings(signUpSettings)); err != nil {
return fmt.Errorf("setting `sign_up`: %+v", err)
}
} else {
d.Set("sign_in", []interface{}{})
d.Set("sign_up", []interface{}{})
}
yupwei68 marked this conversation as resolved.
Show resolved Hide resolved

return tags.FlattenAndSet(d, resp.Tags)
Expand Down Expand Up @@ -1146,7 +1161,7 @@ func flattenApiManagementServiceSkuName(input *apimanagement.ServiceSkuPropertie
return fmt.Sprintf("%s_%d", string(input.Name), *input.Capacity)
}

func expandApiManagementCustomProperties(d *schema.ResourceData) map[string]*string {
func expandApiManagementCustomProperties(d *schema.ResourceData, skuIsConsumption bool) (map[string]*string, error) {
backendProtocolSsl3 := false
backendProtocolTls10 := false
backendProtocolTls11 := false
Expand All @@ -1164,16 +1179,26 @@ func expandApiManagementCustomProperties(d *schema.ResourceData) map[string]*str
frontendProtocolTls10 = v["enable_frontend_tls10"].(bool)
frontendProtocolTls11 = v["enable_frontend_tls11"].(bool)
tripleDesCiphers = v["enable_triple_des_ciphers"].(bool)
if skuIsConsumption && frontendProtocolSsl3 {
return nil, fmt.Errorf("`enable_frontend_ssl30` is not support for Sku Tier `Consumption`")
}

if skuIsConsumption && tripleDesCiphers {
return nil, fmt.Errorf("`enable_triple_des_ciphers` is not support for Sku Tier `Consumption`")
}
}

customProperties := map[string]*string{
apimBackendProtocolSsl3: utils.String(strconv.FormatBool(backendProtocolSsl3)),
apimBackendProtocolTls10: utils.String(strconv.FormatBool(backendProtocolTls10)),
apimBackendProtocolTls11: utils.String(strconv.FormatBool(backendProtocolTls11)),
apimFrontendProtocolSsl3: utils.String(strconv.FormatBool(frontendProtocolSsl3)),
apimFrontendProtocolTls10: utils.String(strconv.FormatBool(frontendProtocolTls10)),
apimFrontendProtocolTls11: utils.String(strconv.FormatBool(frontendProtocolTls11)),
apimTripleDesCiphers: utils.String(strconv.FormatBool(tripleDesCiphers)),
}

if !skuIsConsumption {
customProperties[apimFrontendProtocolSsl3] = utils.String(strconv.FormatBool(frontendProtocolSsl3))
customProperties[apimTripleDesCiphers] = utils.String(strconv.FormatBool(tripleDesCiphers))
}

if vp := d.Get("protocols").([]interface{}); len(vp) > 0 {
Expand All @@ -1182,7 +1207,7 @@ func expandApiManagementCustomProperties(d *schema.ResourceData) map[string]*str
customProperties[apimHttp2Protocol] = utils.String(strconv.FormatBool(enableHttp2))
}

return customProperties
return customProperties, nil
}

func expandAzureRmApiManagementVirtualNetworkConfigurations(d *schema.ResourceData) *apimanagement.VirtualNetworkConfiguration {
Expand All @@ -1199,16 +1224,19 @@ func expandAzureRmApiManagementVirtualNetworkConfigurations(d *schema.ResourceDa
}
}

func flattenApiManagementSecurityCustomProperties(input map[string]*string) []interface{} {
func flattenApiManagementSecurityCustomProperties(input map[string]*string, skuIsConsumption bool) []interface{} {
output := make(map[string]interface{})

output["enable_backend_ssl30"] = parseApiManagementNilableDictionary(input, apimBackendProtocolSsl3)
output["enable_backend_tls10"] = parseApiManagementNilableDictionary(input, apimBackendProtocolTls10)
output["enable_backend_tls11"] = parseApiManagementNilableDictionary(input, apimBackendProtocolTls11)
output["enable_frontend_ssl30"] = parseApiManagementNilableDictionary(input, apimFrontendProtocolSsl3)
output["enable_frontend_tls10"] = parseApiManagementNilableDictionary(input, apimFrontendProtocolTls10)
output["enable_frontend_tls11"] = parseApiManagementNilableDictionary(input, apimFrontendProtocolTls11)
output["enable_triple_des_ciphers"] = parseApiManagementNilableDictionary(input, apimTripleDesCiphers)

if !skuIsConsumption {
output["enable_frontend_ssl30"] = parseApiManagementNilableDictionary(input, apimFrontendProtocolSsl3)
output["enable_triple_des_ciphers"] = parseApiManagementNilableDictionary(input, apimTripleDesCiphers)
}

return []interface{}{output}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,25 @@ func TestAccAzureRMApiManagement_virtualNetworkInternalAdditionalLocation(t *tes
})
}

func TestAccAzureRMApiManagement_consumption(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_consumption(data),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMApiManagementExists(data.ResourceName),
),
},
data.ImportStep(),
},
})
}

// Api Management doesn't support hostname keyvault using UserAssigned Identity
// There will be a inevitable dependency cycle here when using SystemAssigned Identity
// 1. create SystemAssigned Identity, grant the identity certificate access
Expand Down Expand Up @@ -1049,6 +1068,29 @@ resource "azurerm_api_management" "test" {
`, template, data.RandomInteger, data.Locations.Secondary)
}

func testAccAzureRMApiManagement_consumption(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}

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 = "Consumption_0"
}
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger)
}

func testAccAzureRMApiManagement_identityUserAssigned(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
Expand Down
15 changes: 15 additions & 0 deletions azurerm/internal/services/apimanagement/validate/api_management.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package validate

import (
"regexp"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)

func ApimSkuName() schema.SchemaValidateFunc {
return validation.StringMatch(
regexp.MustCompile(`^Consumption_0$|^Basic_(1|2)$|^Developer_1$|^Premium_([1-9]|10)$|^Standard_[1-4]$`),
`This is not a valid Api Management sku name.`,
)
}
Loading