diff --git a/azurerm/config.go b/azurerm/config.go index 565dc05a6311..e08b774daa76 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -126,7 +126,8 @@ type ArmClient struct { redisPatchSchedulesClient redis.PatchSchedulesClient // API Management - apiManagementServiceClient apimanagement.ServiceClient + apiManagementProductsClient apimanagement.ProductClient + apiManagementServiceClient apimanagement.ServiceClient // Application Insights appInsightsClient appinsights.ComponentsClient @@ -487,9 +488,13 @@ func getArmClient(c *authentication.Config, skipProviderRegistration bool, partn } func (c *ArmClient) registerApiManagementServiceClients(endpoint, subscriptionId string, auth autorest.Authorizer) { - ams := apimanagement.NewServiceClientWithBaseURI(endpoint, subscriptionId) - c.configureClient(&ams.Client, auth) - c.apiManagementServiceClient = ams + serviceClient := apimanagement.NewServiceClientWithBaseURI(endpoint, subscriptionId) + c.configureClient(&serviceClient.Client, auth) + c.apiManagementServiceClient = serviceClient + + productsClient := apimanagement.NewProductClientWithBaseURI(endpoint, subscriptionId) + c.configureClient(&productsClient.Client, auth) + c.apiManagementProductsClient = productsClient } func (c *ArmClient) registerAppInsightsClients(endpoint, subscriptionId string, auth autorest.Authorizer) { diff --git a/azurerm/data_source_api_management.go b/azurerm/data_source_api_management.go index 5247b40f947d..c17e8e367071 100644 --- a/azurerm/data_source_api_management.go +++ b/azurerm/data_source_api_management.go @@ -6,7 +6,7 @@ import ( "github.com/Azure/azure-sdk-for-go/services/apimanagement/mgmt/2018-01-01/apimanagement" "github.com/hashicorp/terraform/helper/schema" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -15,11 +15,7 @@ func dataSourceApiManagementService() *schema.Resource { Read: dataSourceApiManagementRead, Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validate.ApiManagementServiceName, - }, + "name": azure.SchemaApiManagementDataSourceName(), "resource_group_name": resourceGroupNameForDataSourceSchema(), diff --git a/azurerm/data_source_api_management_product.go b/azurerm/data_source_api_management_product.go new file mode 100644 index 000000000000..a88446a9f287 --- /dev/null +++ b/azurerm/data_source_api_management_product.go @@ -0,0 +1,90 @@ +package azurerm + +import ( + "fmt" + + "github.com/Azure/azure-sdk-for-go/services/preview/apimanagement/mgmt/2018-06-01-preview/apimanagement" + "github.com/hashicorp/terraform/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceApiManagementProduct() *schema.Resource { + return &schema.Resource{ + Read: dataSourceApiManagementProductRead, + + Schema: map[string]*schema.Schema{ + "product_id": azure.SchemaApiManagementProductDataSourceName(), + + "api_management_name": azure.SchemaApiManagementDataSourceName(), + + "resource_group_name": resourceGroupNameSchema(), + + "display_name": { + Type: schema.TypeString, + Computed: true, + }, + + "subscription_required": { + Type: schema.TypeBool, + Computed: true, + }, + + "approval_required": { + Type: schema.TypeBool, + Computed: true, + }, + + "published": { + Type: schema.TypeBool, + Computed: true, + }, + + "description": { + Type: schema.TypeString, + Computed: true, + }, + + "terms": { + Type: schema.TypeString, + Computed: true, + }, + + "subscriptions_limit": { + Type: schema.TypeInt, + Computed: true, + }, + }, + } +} +func dataSourceApiManagementProductRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementProductsClient + ctx := meta.(*ArmClient).StopContext + + resourceGroup := d.Get("resource_group_name").(string) + serviceName := d.Get("api_management_name").(string) + productId := d.Get("product_id").(string) + + resp, err := client.Get(ctx, resourceGroup, serviceName, productId) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Product %q was not found in API Management Service %q / Resource Group %q", productId, serviceName, resourceGroup) + } + + return fmt.Errorf("Error making Read request on Product %q (API Management Service %q / Resource Group %q): %+v", productId, serviceName, resourceGroup, err) + } + + d.SetId(*resp.ID) + + if props := resp.ProductContractProperties; props != nil { + d.Set("approval_required", props.ApprovalRequired) + d.Set("description", props.Description) + d.Set("display_name", props.DisplayName) + d.Set("published", props.State == apimanagement.Published) + d.Set("subscriptions_limit", props.SubscriptionsLimit) + d.Set("subscription_required", props.SubscriptionRequired) + d.Set("terms", props.Terms) + } + + return nil +} diff --git a/azurerm/data_source_api_management_product_test.go b/azurerm/data_source_api_management_product_test.go new file mode 100644 index 000000000000..17293d2d300d --- /dev/null +++ b/azurerm/data_source_api_management_product_test.go @@ -0,0 +1,76 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" +) + +func TestAccDataSourceAzureRMApiManagementProduct_basic(t *testing.T) { + dataSourceName := "data.azurerm_api_management_product.test" + rInt := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceApiManagementProduct_basic(rInt, location), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "product_id", "test-product"), + resource.TestCheckResourceAttr(dataSourceName, "display_name", "Test Product"), + resource.TestCheckResourceAttr(dataSourceName, "subscription_required", "true"), + resource.TestCheckResourceAttr(dataSourceName, "approval_required", "true"), + resource.TestCheckResourceAttr(dataSourceName, "published", "true"), + resource.TestCheckResourceAttr(dataSourceName, "description", "This is an example description"), + resource.TestCheckResourceAttr(dataSourceName, "terms", "These are some example terms and conditions"), + ), + }, + }, + }) +} + +func testAccDataSourceApiManagementProduct_basic(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "amtestRG-%d" + location = "%s" +} + +resource "azurerm_api_management" "test" { + name = "acctestAM-%d" + publisher_name = "pub1" + publisher_email = "pub1@email.com" + + sku { + name = "Developer" + capacity = 1 + } + + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} + + +resource "azurerm_api_management_product" "test" { + product_id = "test-product" + api_management_name = "${azurerm_api_management.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + display_name = "Test Product" + subscription_required = true + approval_required = true + published = true + description = "This is an example description" + terms = "These are some example terms and conditions" +} + +data "azurerm_api_management_product" "test" { + product_id = "${azurerm_api_management_product.test.product_id}" + api_management_name = "${azurerm_api_management_product.test.api_management_name}" + resource_group_name = "${azurerm_api_management_product.test.resource_group_name}" +} +`, rInt, location, rInt) +} diff --git a/azurerm/helpers/azure/api_management.go b/azurerm/helpers/azure/api_management.go new file mode 100644 index 000000000000..f364e4211a2f --- /dev/null +++ b/azurerm/helpers/azure/api_management.go @@ -0,0 +1,40 @@ +package azure + +import ( + "github.com/hashicorp/terraform/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" +) + +func SchemaApiManagementName() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ApiManagementServiceName, + } +} + +func SchemaApiManagementDataSourceName() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.ApiManagementServiceName, + } +} + +func SchemaApiManagementProductName() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ApiManagementProductName, + } +} + +func SchemaApiManagementProductDataSourceName() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.ApiManagementProductName, + } +} diff --git a/azurerm/helpers/validate/api_management.go b/azurerm/helpers/validate/api_management.go index b0780799a52c..58f7a4f875a2 100644 --- a/azurerm/helpers/validate/api_management.go +++ b/azurerm/helpers/validate/api_management.go @@ -5,6 +5,17 @@ import ( "regexp" ) +func ApiManagementProductName(v interface{}, k string) (warnings []string, errors []error) { + value := v.(string) + + // from the portal: `The field may contain only numbers, letters, and dash (-) sign when preceded and followed by number or a letter.` + if matched := regexp.MustCompile(`(^[a-zA-Z0-9])([a-zA-Z0-9-]{1,78})([a-zA-Z0-9]$)`).Match([]byte(value)); !matched { + errors = append(errors, fmt.Errorf("%q may only contain alphanumeric characters and dashes up to 80 characters in length", k)) + } + + return warnings, errors +} + func ApiManagementServiceName(v interface{}, k string) (warnings []string, errors []error) { value := v.(string) diff --git a/azurerm/provider.go b/azurerm/provider.go index ab4e0a1ed1eb..e3ec6d8d4b6b 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -99,6 +99,7 @@ func Provider() terraform.ResourceProvider { DataSourcesMap: map[string]*schema.Resource{ "azurerm_api_management": dataSourceApiManagementService(), + "azurerm_api_management_product": dataSourceApiManagementProduct(), "azurerm_app_service_plan": dataSourceAppServicePlan(), "azurerm_app_service": dataSourceArmAppService(), "azurerm_application_insights": dataSourceArmApplicationInsights(), @@ -164,6 +165,7 @@ func Provider() terraform.ResourceProvider { ResourcesMap: map[string]*schema.Resource{ "azurerm_api_management": resourceArmApiManagementService(), + "azurerm_api_management_product": resourceArmApiManagementProduct(), "azurerm_app_service_active_slot": resourceArmAppServiceActiveSlot(), "azurerm_app_service_custom_hostname_binding": resourceArmAppServiceCustomHostnameBinding(), "azurerm_app_service_plan": resourceArmAppServicePlan(), diff --git a/azurerm/resource_arm_api_management.go b/azurerm/resource_arm_api_management.go index 2f66a54b72cd..130b1fd23146 100644 --- a/azurerm/resource_arm_api_management.go +++ b/azurerm/resource_arm_api_management.go @@ -34,12 +34,7 @@ func resourceArmApiManagementService() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.ApiManagementServiceName, - }, + "name": azure.SchemaApiManagementName(), "resource_group_name": resourceGroupNameSchema(), diff --git a/azurerm/resource_arm_api_management_product.go b/azurerm/resource_arm_api_management_product.go new file mode 100644 index 000000000000..3770b0600be6 --- /dev/null +++ b/azurerm/resource_arm_api_management_product.go @@ -0,0 +1,204 @@ +package azurerm + +import ( + "fmt" + "log" + + "github.com/Azure/azure-sdk-for-go/services/preview/apimanagement/mgmt/2018-06-01-preview/apimanagement" + "github.com/hashicorp/terraform/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmApiManagementProduct() *schema.Resource { + return &schema.Resource{ + Create: resourceArmApiManagementProductCreateUpdate, + Read: resourceArmApiManagementProductRead, + Update: resourceArmApiManagementProductCreateUpdate, + Delete: resourceArmApiManagementProductDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "product_id": azure.SchemaApiManagementProductName(), + + "api_management_name": azure.SchemaApiManagementName(), + + "resource_group_name": resourceGroupNameSchema(), + + "display_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, + }, + + "subscription_required": { + Type: schema.TypeBool, + Required: true, + }, + + "published": { + Type: schema.TypeBool, + Required: true, + }, + + "approval_required": { + Type: schema.TypeBool, + Optional: true, + }, + + "description": { + Type: schema.TypeString, + Optional: true, + }, + + "terms": { + Type: schema.TypeString, + Optional: true, + }, + + "subscriptions_limit": { + Type: schema.TypeInt, + Optional: true, + }, + }, + } +} + +func resourceArmApiManagementProductCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementProductsClient + ctx := meta.(*ArmClient).StopContext + + log.Printf("[INFO] preparing arguments for API Management Product creation.") + + resourceGroup := d.Get("resource_group_name").(string) + serviceName := d.Get("api_management_name").(string) + productId := d.Get("product_id").(string) + + displayName := d.Get("display_name").(string) + description := d.Get("description").(string) + terms := d.Get("terms").(string) + subscriptionRequired := d.Get("subscription_required").(bool) + approvalRequired := d.Get("approval_required").(bool) + subscriptionsLimit := d.Get("subscriptions_limit").(int) + published := d.Get("published").(bool) + + if requireResourcesToBeImported && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, serviceName, productId) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Product %q (API Management Service %q / Resource Group %q): %s", productId, serviceName, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_api_management_product", *existing.ID) + } + } + publishedVal := apimanagement.NotPublished + if published { + publishedVal = apimanagement.Published + } + + properties := apimanagement.ProductContract{ + ProductContractProperties: &apimanagement.ProductContractProperties{ + Description: utils.String(description), + DisplayName: utils.String(displayName), + State: publishedVal, + SubscriptionRequired: utils.Bool(subscriptionRequired), + Terms: utils.String(terms), + }, + } + + // Swagger says: Can be present only if subscriptionRequired property is present and has a value of false. + // API/Portal says: Cannot provide values for approvalRequired and subscriptionsLimit when subscriptionRequired is set to false in the request payload + if subscriptionRequired && subscriptionsLimit > 0 { + properties.ProductContractProperties.ApprovalRequired = utils.Bool(approvalRequired) + properties.ProductContractProperties.SubscriptionsLimit = utils.Int32(int32(subscriptionsLimit)) + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, serviceName, productId, properties, ""); err != nil { + return fmt.Errorf("Error creating/updating Product %q (API Management Service %q / Resource Group %q): %+v", productId, serviceName, resourceGroup, err) + } + + read, err := client.Get(ctx, resourceGroup, serviceName, productId) + if err != nil { + return fmt.Errorf("Error retrieving Product %q (API Management Service %q / Resource Group %q): %+v", productId, serviceName, resourceGroup, err) + } + + if read.ID == nil { + return fmt.Errorf("Cannot read ID for Product %q (API Management Service %q / Resource Group %q)", productId, serviceName, resourceGroup) + } + + d.SetId(*read.ID) + + return resourceArmApiManagementProductRead(d, meta) +} + +func resourceArmApiManagementProductRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementProductsClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + + resourceGroup := id.ResourceGroup + serviceName := id.Path["service"] + productId := id.Path["products"] + + resp, err := client.Get(ctx, resourceGroup, serviceName, productId) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("Product %q was not found in API Management Service %q / Resource Group %q - removing from state!", productId, serviceName, resourceGroup) + d.SetId("") + return nil + } + + return fmt.Errorf("Error making Read request on Product %q (API Management Service %q / Resource Group %q): %+v", productId, serviceName, resourceGroup, err) + } + + d.Set("product_id", productId) + d.Set("api_management_name", serviceName) + d.Set("resource_group_name", resourceGroup) + + if props := resp.ProductContractProperties; props != nil { + d.Set("approval_required", props.ApprovalRequired) + d.Set("description", props.Description) + d.Set("display_name", props.DisplayName) + d.Set("published", props.State == apimanagement.Published) + d.Set("subscriptions_limit", props.SubscriptionsLimit) + d.Set("subscription_required", props.SubscriptionRequired) + d.Set("terms", props.Terms) + } + + return nil +} + +func resourceArmApiManagementProductDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementProductsClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + serviceName := id.Path["service"] + productId := id.Path["products"] + + log.Printf("[DEBUG] Deleting Product %q (API Management Service %q / Resource Grouo %q)", productId, serviceName, resourceGroup) + deleteSubscriptions := true + resp, err := client.Delete(ctx, resourceGroup, serviceName, productId, "", utils.Bool(deleteSubscriptions)) + if err != nil { + if !utils.ResponseWasNotFound(resp) { + return fmt.Errorf("Error deleting Product %q (API Management Service %q / Resource Group %q): %+v", productId, serviceName, resourceGroup, err) + } + } + + return nil +} diff --git a/azurerm/resource_arm_api_management_product_test.go b/azurerm/resource_arm_api_management_product_test.go new file mode 100644 index 000000000000..d69efc52b3fb --- /dev/null +++ b/azurerm/resource_arm_api_management_product_test.go @@ -0,0 +1,398 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMApiManagementProduct_basic(t *testing.T) { + resourceName := "azurerm_api_management_product.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApiManagementProductDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApiManagementProduct_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementProductExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "approval_required", "false"), + resource.TestCheckResourceAttr(resourceName, "description", ""), + resource.TestCheckResourceAttr(resourceName, "display_name", "Test Product"), + resource.TestCheckResourceAttr(resourceName, "product_id", "test-product"), + resource.TestCheckResourceAttr(resourceName, "published", "false"), + resource.TestCheckResourceAttr(resourceName, "subscription_required", "false"), + resource.TestCheckResourceAttr(resourceName, "terms", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMApiManagementProduct_requiresImport(t *testing.T) { + if !requireResourcesToBeImported { + t.Skip("Skipping since resources aren't required to be imported") + return + } + + resourceName := "azurerm_api_management_product.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApiManagementProductDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApiManagementProduct_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementProductExists(resourceName), + ), + }, + { + Config: testAccAzureRMApiManagementProduct_requiresImport(ri, location), + ExpectError: testRequiresImportError("azurerm_api_management_product"), + }, + }, + }) +} + +func testCheckAzureRMApiManagementProductDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).apiManagementProductsClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_api_management_product" { + continue + } + + productId := rs.Primary.Attributes["product_id"] + serviceName := rs.Primary.Attributes["api_management_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + ctx := testAccProvider.Meta().(*ArmClient).StopContext + resp, err := conn.Get(ctx, resourceGroup, serviceName, productId) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return err + } + + return nil + } + + return nil +} + +func TestAccAzureRMApiManagementProduct_update(t *testing.T) { + resourceName := "azurerm_api_management_product.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApiManagementProductDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApiManagementProduct_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementProductExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "approval_required", "false"), + resource.TestCheckResourceAttr(resourceName, "description", ""), + resource.TestCheckResourceAttr(resourceName, "display_name", "Test Product"), + resource.TestCheckResourceAttr(resourceName, "product_id", "test-product"), + resource.TestCheckResourceAttr(resourceName, "published", "false"), + resource.TestCheckResourceAttr(resourceName, "subscription_required", "false"), + resource.TestCheckResourceAttr(resourceName, "terms", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAzureRMApiManagementProduct_updated(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementProductExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "approval_required", "true"), + resource.TestCheckResourceAttr(resourceName, "description", ""), + resource.TestCheckResourceAttr(resourceName, "display_name", "Test Updated Product"), + resource.TestCheckResourceAttr(resourceName, "product_id", "test-product"), + resource.TestCheckResourceAttr(resourceName, "published", "true"), + resource.TestCheckResourceAttr(resourceName, "subscription_required", "true"), + resource.TestCheckResourceAttr(resourceName, "terms", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAzureRMApiManagementProduct_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementProductExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "approval_required", "false"), + resource.TestCheckResourceAttr(resourceName, "description", ""), + resource.TestCheckResourceAttr(resourceName, "display_name", "Test Product"), + resource.TestCheckResourceAttr(resourceName, "product_id", "test-product"), + resource.TestCheckResourceAttr(resourceName, "published", "false"), + resource.TestCheckResourceAttr(resourceName, "subscription_required", "false"), + resource.TestCheckResourceAttr(resourceName, "terms", ""), + ), + }, + }, + }) +} + +func TestAccAzureRMApiManagementProduct_subscriptionsLimit(t *testing.T) { + resourceName := "azurerm_api_management_product.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApiManagementProductDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApiManagementProduct_subscriptionLimits(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementProductExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "approval_required", "true"), + resource.TestCheckResourceAttr(resourceName, "subscription_required", "true"), + resource.TestCheckResourceAttr(resourceName, "subscriptions_limit", "2"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMApiManagementProduct_complete(t *testing.T) { + resourceName := "azurerm_api_management_product.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApiManagementProductDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApiManagementProduct_complete(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementProductExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "approval_required", "true"), + resource.TestCheckResourceAttr(resourceName, "description", "This is an example description"), + resource.TestCheckResourceAttr(resourceName, "display_name", "Test Product"), + resource.TestCheckResourceAttr(resourceName, "product_id", "test-product"), + resource.TestCheckResourceAttr(resourceName, "published", "true"), + resource.TestCheckResourceAttr(resourceName, "subscriptions_limit", "2"), + resource.TestCheckResourceAttr(resourceName, "subscription_required", "true"), + resource.TestCheckResourceAttr(resourceName, "terms", "These are some example terms and conditions"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testCheckAzureRMApiManagementProductExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + productId := rs.Primary.Attributes["product_id"] + serviceName := rs.Primary.Attributes["api_management_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + conn := testAccProvider.Meta().(*ArmClient).apiManagementProductsClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + resp, err := conn.Get(ctx, resourceGroup, serviceName, productId) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Product %q (API Management Service %q / Resource Group %q) does not exist", productId, serviceName, resourceGroup) + } + + return fmt.Errorf("Bad: Get on apiManagementProductsClient: %+v", err) + } + + return nil + } +} + +func testAccAzureRMApiManagementProduct_basic(rInt int, location string) string { + return fmt.Sprintf(` +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 = "Developer" + capacity = 1 + } +} + +resource "azurerm_api_management_product" "test" { + product_id = "test-product" + api_management_name = "${azurerm_api_management.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + display_name = "Test Product" + subscription_required = false + published = false +} +`, rInt, location, rInt) +} + +func testAccAzureRMApiManagementProduct_requiresImport(rInt int, location string) string { + template := testAccAzureRMApiManagementProduct_basic(rInt, location) + return fmt.Sprintf(` +%s + +resource "azurerm_api_management_product" "import" { + product_id = "${azurerm_api_management_product.test.product_id}" + api_management_name = "${azurerm_api_management_product.test.api_management_name}" + resource_group_name = "${azurerm_api_management_product.test.resource_group_name}" + display_name = "${azurerm_api_management_product.test.display_name}" + subscription_required = "${azurerm_api_management_product.test.subscription_required}" + approval_required = "${azurerm_api_management_product.test.approval_required}" + published = "${azurerm_api_management_product.test.published}" +} +`, template) +} + +func testAccAzureRMApiManagementProduct_updated(rInt int, location string) string { + return fmt.Sprintf(` +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 = "Developer" + capacity = 1 + } +} + +resource "azurerm_api_management_product" "test" { + product_id = "test-product" + api_management_name = "${azurerm_api_management.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + display_name = "Test Updated Product" + subscription_required = true + approval_required = true + published = true +} +`, rInt, location, rInt) +} + +func testAccAzureRMApiManagementProduct_subscriptionLimits(rInt int, location string) string { + return fmt.Sprintf(` +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 = "Developer" + capacity = 1 + } +} + +resource "azurerm_api_management_product" "test" { + product_id = "test-product" + api_management_name = "${azurerm_api_management.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + display_name = "Test Product" + subscription_required = true + approval_required = true + subscriptions_limit = 2 + published = false +} +`, rInt, location, rInt) +} + +func testAccAzureRMApiManagementProduct_complete(rInt int, location string) string { + return fmt.Sprintf(` +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 = "Developer" + capacity = 1 + } +} + +resource "azurerm_api_management_product" "test" { + product_id = "test-product" + api_management_name = "${azurerm_api_management.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + display_name = "Test Product" + subscription_required = true + approval_required = true + published = true + subscriptions_limit = 2 + description = "This is an example description" + terms = "These are some example terms and conditions" +} +`, rInt, location, rInt) +} diff --git a/website/azurerm.erb b/website/azurerm.erb index 0e1da4ccfce9..b8c7f680aef2 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -59,9 +59,12 @@