From a3e1fdd84c88ca429ed5bb9995abb05105af9ffb Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 1 Mar 2019 15:08:29 +0100 Subject: [PATCH 1/4] New Resource: `azurerm_api_management_product_group` --- azurerm/config.go | 15 +- azurerm/provider.go | 1 + ...source_arm_api_management_product_group.go | 121 ++++++++++++ ...e_arm_api_management_product_group_test.go | 176 ++++++++++++++++++ website/azurerm.erb | 6 +- .../r/api_management_group_user.html.markdown | 1 - .../r/api_management_product.html.markdown | 4 +- ...api_management_product_group.html.markdown | 65 +++++++ 8 files changed, 380 insertions(+), 9 deletions(-) create mode 100644 azurerm/resource_arm_api_management_product_group.go create mode 100644 azurerm/resource_arm_api_management_product_group_test.go create mode 100644 website/docs/r/api_management_product_group.html.markdown diff --git a/azurerm/config.go b/azurerm/config.go index 3f3a422c6038..d475ab0424d1 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -126,11 +126,12 @@ type ArmClient struct { redisPatchSchedulesClient redis.PatchSchedulesClient // API Management - apiManagementGroupClient apimanagement.GroupClient - apiManagementGroupUsersClient apimanagement.GroupUserClient - apiManagementProductsClient apimanagement.ProductClient - apiManagementServiceClient apimanagement.ServiceClient - apiManagementUsersClient apimanagement.UserClient + apiManagementGroupClient apimanagement.GroupClient + apiManagementGroupUsersClient apimanagement.GroupUserClient + apiManagementProductsClient apimanagement.ProductClient + apiManagementProductGroupsClient apimanagement.ProductGroupClient + apiManagementServiceClient apimanagement.ServiceClient + apiManagementUsersClient apimanagement.UserClient // Application Insights appInsightsClient appinsights.ComponentsClient @@ -507,6 +508,10 @@ func (c *ArmClient) registerApiManagementServiceClients(endpoint, subscriptionId c.configureClient(&productsClient.Client, auth) c.apiManagementProductsClient = productsClient + productGroupsClient := apimanagement.NewProductGroupClientWithBaseURI(endpoint, subscriptionId) + c.configureClient(&productGroupsClient.Client, auth) + c.apiManagementProductGroupsClient = productGroupsClient + usersClient := apimanagement.NewUserClientWithBaseURI(endpoint, subscriptionId) c.configureClient(&usersClient.Client, auth) c.apiManagementUsersClient = usersClient diff --git a/azurerm/provider.go b/azurerm/provider.go index ce0a57c84047..f65e00a41025 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -171,6 +171,7 @@ func Provider() terraform.ResourceProvider { "azurerm_api_management_group": resourceArmApiManagementGroup(), "azurerm_api_management_group_user": resourceArmApiManagementGroupUser(), "azurerm_api_management_product": resourceArmApiManagementProduct(), + "azurerm_api_management_product_group": resourceArmApiManagementProductGroup(), "azurerm_api_management_user": resourceArmApiManagementUser(), "azurerm_app_service_active_slot": resourceArmAppServiceActiveSlot(), "azurerm_app_service_custom_hostname_binding": resourceArmAppServiceCustomHostnameBinding(), diff --git a/azurerm/resource_arm_api_management_product_group.go b/azurerm/resource_arm_api_management_product_group.go new file mode 100644 index 000000000000..88f4aa85e641 --- /dev/null +++ b/azurerm/resource_arm_api_management_product_group.go @@ -0,0 +1,121 @@ +package azurerm + +import ( + "fmt" + "log" + + "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/utils" +) + +func resourceArmApiManagementProductGroup() *schema.Resource { + return &schema.Resource{ + Create: resourceArmApiManagementProductGroupCreate, + Read: resourceArmApiManagementProductGroupRead, + Delete: resourceArmApiManagementProductGroupDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "product_id": azure.SchemaApiManagementChildName(), + + "group_name": azure.SchemaApiManagementChildName(), + + "resource_group_name": resourceGroupNameSchema(), + + "api_management_name": azure.SchemaApiManagementName(), + }, + } +} + +func resourceArmApiManagementProductGroupCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementProductGroupsClient + ctx := meta.(*ArmClient).StopContext + + resourceGroup := d.Get("resource_group_name").(string) + serviceName := d.Get("api_management_name").(string) + groupName := d.Get("group_name").(string) + productId := d.Get("product_id").(string) + + if requireResourcesToBeImported { + resp, err := client.CheckEntityExists(ctx, resourceGroup, serviceName, productId, groupName) + if err != nil { + if !utils.ResponseWasNotFound(resp) { + return fmt.Errorf("Error checking for present of existing Product %q / Group %q (API Management Service %q / Resource Group %q): %+v", productId, groupName, serviceName, resourceGroup, err) + } + } + + if !utils.ResponseWasNotFound(resp) { + subscriptionId := meta.(*ArmClient).subscriptionId + resourceId := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.ApiManagement/service/%s/products/%s/groups/%s", subscriptionId, resourceGroup, serviceName, groupName, productId) + return tf.ImportAsExistsError("azurerm_api_management_product_group", resourceId) + } + } + + resp, err := client.CreateOrUpdate(ctx, resourceGroup, serviceName, productId, groupName) + if err != nil { + return fmt.Errorf("Error adding Product %q to Group %q (API Management Service %q / Resource Group %q): %+v", productId, groupName, serviceName, resourceGroup, err) + } + + // there's no Read so this is best-effort + d.SetId(*resp.ID) + + return resourceArmApiManagementProductGroupRead(d, meta) +} + +func resourceArmApiManagementProductGroupRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementProductGroupsClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + serviceName := id.Path["service"] + groupName := id.Path["groups"] + productId := id.Path["products"] + + resp, err := client.CheckEntityExists(ctx, resourceGroup, serviceName, productId, groupName) + if err != nil { + if utils.ResponseWasNotFound(resp) { + log.Printf("[DEBUG] Product %q was not found in Group %q (API Management Service %q / Resource Group %q) was not found - removing from state!", productId, groupName, serviceName, resourceGroup) + d.SetId("") + return nil + } + + return fmt.Errorf("Error retrieving Product %q / Group %q (API Management Service %q / Resource Group %q): %+v", productId, groupName, serviceName, resourceGroup, err) + } + + d.Set("group_name", groupName) + d.Set("product_id", productId) + d.Set("resource_group_name", resourceGroup) + d.Set("api_management_name", serviceName) + + return nil +} + +func resourceArmApiManagementProductGroupDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementGroupUsersClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + serviceName := id.Path["service"] + groupName := id.Path["groups"] + productId := id.Path["products"] + + if resp, err := client.Delete(ctx, resourceGroup, serviceName, productId, groupName); err != nil { + if !utils.ResponseWasNotFound(resp) { + return fmt.Errorf("Error removing Product %q from Group %q (API Management Service %q / Resource Group %q): %+v", productId, groupName, serviceName, resourceGroup, err) + } + } + + return nil +} diff --git a/azurerm/resource_arm_api_management_product_group_test.go b/azurerm/resource_arm_api_management_product_group_test.go new file mode 100644 index 000000000000..d7a1731969a5 --- /dev/null +++ b/azurerm/resource_arm_api_management_product_group_test.go @@ -0,0 +1,176 @@ +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 TestAccAzureRMAPIManagementProductGroup_basic(t *testing.T) { + resourceName := "azurerm_api_management_product_group.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAPIManagementProductGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAPIManagementProductGroup_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAPIManagementProductGroupExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMAPIManagementProductGroup_requiresImport(t *testing.T) { + if !requireResourcesToBeImported { + t.Skip("Skipping since resources aren't required to be imported") + return + } + + resourceName := "azurerm_api_management_product_group.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAPIManagementProductGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAPIManagementProductGroup_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAPIManagementProductGroupExists(resourceName), + ), + }, + { + Config: testAccAzureRMAPIManagementProductGroup_requiresImport(ri, location), + ExpectError: testRequiresImportError("azurerm_api_management_product_group"), + }, + }, + }) +} + +func testCheckAzureRMAPIManagementProductGroupDestroy(s *terraform.State) error { + client := testAccProvider.Meta().(*ArmClient).apiManagementGroupUsersClient + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_api_management_product_group" { + continue + } + + productId := rs.Primary.Attributes["product_id"] + groupName := rs.Primary.Attributes["group_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + serviceName := rs.Primary.Attributes["api_management_name"] + + ctx := testAccProvider.Meta().(*ArmClient).StopContext + resp, err := client.CheckEntityExists(ctx, resourceGroup, serviceName, productId, groupName) + if err != nil { + if !utils.ResponseWasNotFound(resp) { + return err + } + } + + return nil + } + return nil +} + +func testCheckAzureRMAPIManagementProductGroupExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + productId := rs.Primary.Attributes["product_id"] + groupName := rs.Primary.Attributes["group_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + serviceName := rs.Primary.Attributes["api_management_name"] + + client := testAccProvider.Meta().(*ArmClient).apiManagementProductGroupsClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + resp, err := client.CheckEntityExists(ctx, resourceGroup, serviceName, productId, groupName) + if err != nil { + if utils.ResponseWasNotFound(resp) { + return fmt.Errorf("Bad: Product %q / Group %q (API Management Service %q / Resource Group %q) does not exist", productId, groupName, serviceName, resourceGroup) + } + return fmt.Errorf("Bad: Get on apiManagementProductGroupsClient: %+v", err) + } + + return nil + } +} + +func testAccAzureRMAPIManagementProductGroup_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 = true + approval_required = true + published = true +} + +resource "azurerm_api_management_group" "test" { + name = "acctestAMGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + api_management_name = "${azurerm_api_management.test.name}" + display_name = "Test Group" +} + +resource "azurerm_api_management_product_group" "test" { + product_id = "${azurerm_api_management_product.test.product_id}" + group_name = "${azurerm_api_management_group.test.name}" + api_management_name = "${azurerm_api_management.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, rInt, location, rInt, rInt) +} + +func testAccAzureRMAPIManagementProductGroup_requiresImport(rInt int, location string) string { + template := testAccAzureRMAPIManagementProductGroup_basic(rInt, location) + return fmt.Sprintf(` +%s + +resource "azurerm_api_management_product_group" "import" { + product_id = "${azurerm_api_management_product_group.test.product_id}" + group_name = "${azurerm_api_management_product_group.test.group_name}" + api_management_name = "${azurerm_api_management_product_group.test.api_management_name}" + resource_group_name = "${azurerm_api_management_product_group.test.resource_group_name}" +} +`, template) +} diff --git a/website/azurerm.erb b/website/azurerm.erb index 7463396c0272..fbf41b5d216e 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -338,9 +338,13 @@ azurerm_api_management_group_user - > + > azurerm_api_management_product + + > + azurerm_api_management_product_group + diff --git a/website/docs/r/api_management_group_user.html.markdown b/website/docs/r/api_management_group_user.html.markdown index b8b6f3d16c11..80b5151e8a36 100644 --- a/website/docs/r/api_management_group_user.html.markdown +++ b/website/docs/r/api_management_group_user.html.markdown @@ -52,6 +52,5 @@ In addition to all arguments above, the following attributes are exported: API Management Group Users can be imported using the `resource id`, e.g. ```shell - terraform import azurerm_api_management_group_user.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.ApiManagement/service/service1/groups/groupId/users/user123 ``` diff --git a/website/docs/r/api_management_product.html.markdown b/website/docs/r/api_management_product.html.markdown index ca0b6aca4771..c42a30241be7 100644 --- a/website/docs/r/api_management_product.html.markdown +++ b/website/docs/r/api_management_product.html.markdown @@ -1,7 +1,7 @@ --- layout: "azurerm" page_title: "Azure Resource Manager: azurerm_api_management_product" -sidebar_current: "docs-azurerm-resource-api-management-product" +sidebar_current: "docs-azurerm-resource-api-management-product-x" description: |- Manages an API Management Product. --- @@ -68,7 +68,7 @@ The following arguments are supported: * `subscriptions_limit` - (Optional) The number of subscriptions a user can have to this Product at the same time. --> **NOTE:** `subscriptions_limit` can only be set when `subscription_required` is set to `true`. +-> **NOTE:** `subscriptions_limit` can only be set when `subscription_required` is set to `true`. * `terms` - (Optional) The Terms and Conditions for this Product, which must be accepted by Developers before they can begin the Subscription process. diff --git a/website/docs/r/api_management_product_group.html.markdown b/website/docs/r/api_management_product_group.html.markdown new file mode 100644 index 000000000000..ca5ee96ba933 --- /dev/null +++ b/website/docs/r/api_management_product_group.html.markdown @@ -0,0 +1,65 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_api_management_product_group" +sidebar_current: "docs-azurerm-resource-api-management-product-group" +description: |- + Manages an API Management Product Assignment to a Group. +--- + +# azurerm_api_management_product_group + +Manages an API Management Product Assignment to a Group. + +## Example Usage + +```hcl +data "azurerm_api_management" "example" { + name = "example-api" + resource_group_name = "example-resources" +} + +data "azurerm_api_management_product" "example" { + product_id = "my-product" + api_management_name = "${data.azurerm_api_management.example.name}" + resource_group_name = "${data.azurerm_api_management.example.resource_group_name}" +} + +data "azurerm_api_management_group" "example" { + name = "my-group" + api_management_name = "${data.azurerm_api_management.example.name}" + resource_group_name = "${data.azurerm_api_management.example.resource_group_name}" +} + +resource "azurerm_api_management_group_user" "example" { + user_id = "${data.azurerm_api_management_user.example.id}" + group_name = "${data.azurerm_api_management_group.example.name}" + api_management_name = "${data.azurerm_api_management.example.name}" + resource_group_name = "${data.azurerm_api_management.example.resource_group_name}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `user_id` - (Required) The ID of the API Management User which should be assigned to this API Management Group. Changing this forces a new resource to be created. + +* `group_name` - (Required) The Name of the API Management Group within the API Management Service. Changing this forces a new resource to be created. + +* `api_management_name` - (Required) The name of the API Management Service. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the Resource Group in which the API Management Service exists. Changing this forces a new resource to be created. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The ID of the API Management Product Group. + +## Import + +API Management Product Groups can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_api_management_product_group.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.ApiManagement/service/service1/products/exampleId/groups/groupId +``` From 7aa9ecd62f787c4129d40328c12133ea58f1eb9a Mon Sep 17 00:00:00 2001 From: kt Date: Fri, 1 Mar 2019 13:38:59 -0800 Subject: [PATCH 2/4] Update azurerm/resource_arm_api_management_product_group_test.go --- azurerm/resource_arm_api_management_product_group_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_api_management_product_group_test.go b/azurerm/resource_arm_api_management_product_group_test.go index d7a1731969a5..f1b29677d589 100644 --- a/azurerm/resource_arm_api_management_product_group_test.go +++ b/azurerm/resource_arm_api_management_product_group_test.go @@ -153,7 +153,7 @@ resource "azurerm_api_management_group" "test" { } resource "azurerm_api_management_product_group" "test" { - product_id = "${azurerm_api_management_product.test.product_id}" + product_id = "${azurerm_api_management_product.test.product_id}" group_name = "${azurerm_api_management_group.test.name}" api_management_name = "${azurerm_api_management.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" From d963b19473e312fb866c71e261d0d29a7162032f Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 4 Mar 2019 11:33:36 +0100 Subject: [PATCH 3/4] fixing the test --- azurerm/resource_arm_api_management_product_group_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_api_management_product_group_test.go b/azurerm/resource_arm_api_management_product_group_test.go index f1b29677d589..a5fd44fe55c2 100644 --- a/azurerm/resource_arm_api_management_product_group_test.go +++ b/azurerm/resource_arm_api_management_product_group_test.go @@ -141,7 +141,7 @@ resource "azurerm_api_management_product" "test" { resource_group_name = "${azurerm_resource_group.test.name}" display_name = "Test Product" subscription_required = true - approval_required = true + approval_required = false published = true } From 4a8615ccda70303624833430d7baabb5f58d3e13 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 4 Mar 2019 14:53:08 +0100 Subject: [PATCH 4/4] r/api_management_product_group: helps if you call the right client --- azurerm/resource_arm_api_management_product_group.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_api_management_product_group.go b/azurerm/resource_arm_api_management_product_group.go index 88f4aa85e641..13ad8e42c3a3 100644 --- a/azurerm/resource_arm_api_management_product_group.go +++ b/azurerm/resource_arm_api_management_product_group.go @@ -99,7 +99,7 @@ func resourceArmApiManagementProductGroupRead(d *schema.ResourceData, meta inter } func resourceArmApiManagementProductGroupDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient).apiManagementGroupUsersClient + client := meta.(*ArmClient).apiManagementProductGroupsClient ctx := meta.(*ArmClient).StopContext id, err := parseAzureResourceID(d.Id())