From 9597bd8ec0ea482c5e80fb61d01cf8f7d55355c2 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Thu, 2 May 2019 15:52:30 -0600 Subject: [PATCH 1/5] Start of api policy --- azurerm/config.go | 5 + azurerm/provider.go | 1 + .../resource_arm_api_management_api_policy.go | 164 ++++++++++++ ...urce_arm_api_management_api_policy_test.go | 248 ++++++++++++++++++ 4 files changed, 418 insertions(+) create mode 100644 azurerm/resource_arm_api_management_api_policy.go create mode 100644 azurerm/resource_arm_api_management_api_policy_test.go diff --git a/azurerm/config.go b/azurerm/config.go index 8b0a069070eb..f855959cfbb1 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -131,6 +131,7 @@ type ArmClient struct { // API Management apiManagementApiClient apimanagement.APIClient + apiManagementApiPoliciesClient apimanagement.APIPolicyClient apiManagementApiOperationsClient apimanagement.APIOperationClient apiManagementApiVersionSetClient apimanagement.APIVersionSetClient apiManagementAuthorizationServersClient apimanagement.AuthorizationServerClient @@ -537,6 +538,10 @@ func (c *ArmClient) registerApiManagementServiceClients(endpoint, subscriptionId c.configureClient(&apisClient.Client, auth) c.apiManagementApiClient = apisClient + apiPoliciesClient := apimanagement.NewAPIPolicyClientWithBaseURI(endpoint, subscriptionId) + c.configureClient(&apiPoliciesClient.Client, auth) + c.apiManagementApiPoliciesClient = apiPoliciesClient + apiOperationsClient := apimanagement.NewAPIOperationClientWithBaseURI(endpoint, subscriptionId) c.configureClient(&apiOperationsClient.Client, auth) c.apiManagementApiOperationsClient = apiOperationsClient diff --git a/azurerm/provider.go b/azurerm/provider.go index 60eeed2e8886..3f8712ada218 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -176,6 +176,7 @@ func Provider() terraform.ResourceProvider { "azurerm_api_management": resourceArmApiManagementService(), "azurerm_api_management_api": resourceArmApiManagementApi(), "azurerm_api_management_api_operation": resourceArmApiManagementApiOperation(), + "azurerm_api_management_api_policy": resourceArmApiManagementApiPolicy(), "azurerm_api_management_api_version_set": resourceArmApiManagementApiVersionSet(), "azurerm_api_management_authorization_server": resourceArmApiManagementAuthorizationServer(), "azurerm_api_management_certificate": resourceArmApiManagementCertificate(), diff --git a/azurerm/resource_arm_api_management_api_policy.go b/azurerm/resource_arm_api_management_api_policy.go new file mode 100644 index 000000000000..ee0de1752ded --- /dev/null +++ b/azurerm/resource_arm_api_management_api_policy.go @@ -0,0 +1,164 @@ +package azurerm + +import ( + "fmt" + "log" + + "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/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmApiManagementApiPolicy() *schema.Resource { + return &schema.Resource{ + Create: resourceArmApiManagementAPIPolicyCreateUpdate, + Read: resourceArmApiManagementAPIPolicyRead, + Update: resourceArmApiManagementAPIPolicyCreateUpdate, + Delete: resourceArmApiManagementAPIPolicyDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "resource_group_name": resourceGroupNameSchema(), + + "api_management_name": azure.SchemaApiManagementName(), + + "api_name": azure.SchemaApiManagementChildName(), + + "xml_content": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ConflictsWith: []string{"xml_link"}, + DiffSuppressFunc: suppress.XmlDiff, + }, + + "xml_link": { + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"xml_content"}, + }, + }, + } +} + +func resourceArmApiManagementAPIPolicyCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementApiPoliciesClient + ctx := meta.(*ArmClient).StopContext + + resourceGroup := d.Get("resource_group_name").(string) + serviceName := d.Get("api_management_name").(string) + apiName := d.Get("api_name").(string) + + if requireResourcesToBeImported && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, serviceName, apiName) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing API Policy (API Management Service %q / API %q / Resource Group %q): %s", serviceName, apiName, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_api_management_api_policy", *existing.ID) + } + } + + parameters := apimanagement.PolicyContract{} + + xmlContent := d.Get("xml_content").(string) + xmlLink := d.Get("xml_link").(string) + + if xmlContent != "" { + parameters.PolicyContractProperties = &apimanagement.PolicyContractProperties{ + ContentFormat: apimanagement.XML, + PolicyContent: utils.String(xmlContent), + } + } + + if xmlLink != "" { + parameters.PolicyContractProperties = &apimanagement.PolicyContractProperties{ + ContentFormat: apimanagement.XMLLink, + PolicyContent: utils.String(xmlLink), + } + } + + if parameters.PolicyContractProperties == nil { + return fmt.Errorf("Either `xml_content` or `xml_link` must be set") + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, serviceName, apiName, parameters, ""); err != nil { + return fmt.Errorf("Error creating or updating API Policy (Resource Group %q / API Management Service %q / API %q): %+v", resourceGroup, serviceName, apiName, err) + } + + resp, err := client.Get(ctx, resourceGroup, serviceName, apiName) + if err != nil { + return fmt.Errorf("Error retrieving API Policy (Resource Group %q / API Management Service %q / API %q): %+v", resourceGroup, serviceName, apiName, err) + } + if resp.ID == nil { + return fmt.Errorf("Cannot read ID for API Policy (Resource Group %q / API Management Service %q / API %q): %+v", resourceGroup, serviceName, apiName, err) + } + d.SetId(*resp.ID) + + return resourceArmApiManagementAPIPolicyRead(d, meta) +} + +func resourceArmApiManagementAPIPolicyRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementApiPoliciesClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + serviceName := id.Path["service"] + apiName := id.Path["apis"] + + resp, err := client.Get(ctx, resourceGroup, serviceName, apiName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] API Policy (Resource Group %q / API Management Service %q / API %q) was not found - removing from state!", resourceGroup, serviceName, apiName) + d.SetId("") + return nil + } + + return fmt.Errorf("Error making Read request for API Policy (Resource Group %q / API Management Service %q / API %q): %+v", resourceGroup, serviceName, apiName, err) + } + + d.Set("resource_group_name", resourceGroup) + d.Set("api_management_name", serviceName) + d.Set("api_name", apiName) + + if properties := resp.PolicyContractProperties; properties != nil { + // when you submit an `xml_link` to the API, the API downloads this link and stores it as `xml_content` + // as such there is no way to set `xml_link` and we'll let Terraform handle it + d.Set("xml_content", properties.PolicyContent) + } + + return nil +} + +func resourceArmApiManagementAPIPolicyDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementApiPoliciesClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + serviceName := id.Path["service"] + apiName := id.Path["apis"] + + if resp, err := client.Delete(ctx, resourceGroup, serviceName, apiName, ""); err != nil { + if !utils.ResponseWasNotFound(resp) { + return fmt.Errorf("Error deleting API Policy (Resource Group %q / API Management Service %q / API %q): %+v", resourceGroup, serviceName, apiName, err) + } + } + + return nil +} diff --git a/azurerm/resource_arm_api_management_api_policy_test.go b/azurerm/resource_arm_api_management_api_policy_test.go new file mode 100644 index 000000000000..5b7ef389a7f6 --- /dev/null +++ b/azurerm/resource_arm_api_management_api_policy_test.go @@ -0,0 +1,248 @@ +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 TestAccAzureRMApiManagementAPIPolicy_basic(t *testing.T) { + resourceName := "azurerm_api_management_api_policy.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApiManagementAPIPolicyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApiManagementAPIPolicy_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementAPIPolicyExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"xml_link"}, + }, + }, + }) +} + +func TestAccAzureRMApiManagementAPIPolicy_requiresImport(t *testing.T) { + if !requireResourcesToBeImported { + t.Skip("Skipping since resources aren't required to be imported") + return + } + + resourceName := "azurerm_api_management_api_policy.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApiManagementAPIPolicyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApiManagementAPIPolicy_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementAPIPolicyExists(resourceName), + ), + }, + { + Config: testAccAzureRMApiManagementAPIPolicy_requiresImport(ri, location), + ExpectError: testRequiresImportError("azurerm_api_management_api_policy"), + }, + }, + }) +} + +func TestAccAzureRMApiManagementAPIPolicy_update(t *testing.T) { + resourceName := "azurerm_api_management_api_policy.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApiManagementAPIPolicyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApiManagementAPIPolicy_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementAPIPolicyExists(resourceName), + ), + }, + { + Config: testAccAzureRMApiManagementAPIPolicy_updated(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementAPIPolicyExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"xml_link"}, + }, + }, + }) +} + +func testCheckAzureRMApiManagementAPIPolicyExists(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) + } + + apiName := rs.Primary.Attributes["api_name"] + serviceName := rs.Primary.Attributes["api_management_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + conn := testAccProvider.Meta().(*ArmClient).apiManagementApiPoliciesClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + resp, err := conn.Get(ctx, resourceGroup, serviceName, apiName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: API Policy (API Management Service %q / API %q/ Resource Group %q) does not exist", serviceName, apiName, resourceGroup) + } + + return fmt.Errorf("Bad: Get on apiManagementAPIPoliciesClient: %+v", err) + } + + return nil + } +} + +func testCheckAzureRMApiManagementAPIPolicyDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).apiManagementApiPoliciesClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_api_management_api_policy" { + continue + } + + apiName := rs.Primary.Attributes["api_name"] + 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, apiName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return err + } + + return nil + } + + return nil +} + +func testAccAzureRMApiManagementAPIPolicy_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_api" "test" { + name = "acctestapi-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + api_management_name = "${azurerm_api_management.test.name}" + display_name = "api1" + path = "api1" + protocols = ["https"] + revision = "1" +} + +resource "azurerm_api_management_api_policy" "test" { + api_name = "${azurerm_api_management_api.test.name}" + api_management_name = "${azurerm_api_management.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + xml_link = "https://gist.githubusercontent.com/tombuildsstuff/4f58581599d2c9f64b236f505a361a67/raw/0d29dcb0167af1e5afe4bd52a6d7f69ba1e05e1f/example.xml" +} +`, rInt, location, rInt, rInt) +} + +func testAccAzureRMApiManagementAPIPolicy_requiresImport(rInt int, location string) string { + template := testAccAzureRMApiManagementAPIPolicy_basic(rInt, location) + return fmt.Sprintf(` +%s + +resource "azurerm_api_management_api_policy" "import" { + api_name = "${azurerm_api_management_api_policy.test.api_name}" + api_management_name = "${azurerm_api_management_api_policy.test.api_management_name}" + resource_group_name = "${azurerm_api_management_api_policy.test.resource_group_name}" + xml_link = "${azurerm_api_management_api_policy.test.xml_link}" +} +`, template) +} + +func testAccAzureRMApiManagementAPIPolicy_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_api" "test" { + name = "acctestapi-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + api_management_name = "${azurerm_api_management.test.name}" + display_name = "api1" + path = "api1" + protocols = ["https"] + revision = "1" +} + +resource "azurerm_api_management_api_policy" "test" { + api_name = "${azurerm_api_management_api.test.name}" + api_management_name = "${azurerm_api_management.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + xml_content = < + + + + +XML +} +`, rInt, location, rInt, rInt) +} From 8816dabd352a9c3d6c44c457e155a52a9bb6b684 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Thu, 2 May 2019 17:09:28 -0600 Subject: [PATCH 2/5] Finishing api policy --- ...urce_arm_api_management_api_policy_test.go | 3 +- website/azurerm.erb | 4 ++ .../r/api_management_api_policy.html.markdown | 65 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 website/docs/r/api_management_api_policy.html.markdown diff --git a/azurerm/resource_arm_api_management_api_policy_test.go b/azurerm/resource_arm_api_management_api_policy_test.go index 5b7ef389a7f6..78bac8824332 100644 --- a/azurerm/resource_arm_api_management_api_policy_test.go +++ b/azurerm/resource_arm_api_management_api_policy_test.go @@ -236,7 +236,8 @@ resource "azurerm_api_management_api_policy" "test" { api_name = "${azurerm_api_management_api.test.name}" api_management_name = "${azurerm_api_management.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" - xml_content = < diff --git a/website/azurerm.erb b/website/azurerm.erb index d1f74c33bfc8..92c09987b81f 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -365,6 +365,10 @@ > azurerm_api_management_api_operation + + > + azurerm_api_management_api_policy + > azurerm_api_management_version_set diff --git a/website/docs/r/api_management_api_policy.html.markdown b/website/docs/r/api_management_api_policy.html.markdown new file mode 100644 index 000000000000..fbc000c7e81a --- /dev/null +++ b/website/docs/r/api_management_api_policy.html.markdown @@ -0,0 +1,65 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_api_management_api_policy" +sidebar_current: "docs-azurerm-resource-api-management-api-policy" +description: |- + Manages an API Management API Policy +--- + +# azurerm_api_management_api_policy + +Manages an API Management API Policy + + +## Example Usage + +```hcl +data "azurerm_api_management_api" "example" { + api_name = "my-api" + api_management_name = "example-apim" + resource_group_name = "search-service" +} + +resource "azurerm_api_management_api_policy" "example" { + api_name = "${data.azurerm_api_management_api.example.name}" + api_management_name = "${data.azurerm_api_management_api.example.api_management_name}" + resource_group_name = "${data.azurerm_api_management_api.example.resource_group_name}" + + xml_content = < + + + + +XML +} +``` + + +## Argument Reference + +The following arguments are supported: + +* `api_name` - (Required) The ID of the API Management API 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. + +* `xml_content` - (Optional) The XML Content for this Policy. + +* `xml_link` - (Optional) A link to a Policy XML Document, which must be publicly available. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The ID of the API Management API Policy. + +## Import + +API Management API Policy can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_api_management_api_policy.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.ApiManagement/service/service1/apis/exampleId/policies/policy +``` From b5a52b36b7b41778be1db72cabe15976e42f929c Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Fri, 3 May 2019 09:13:11 -0600 Subject: [PATCH 3/5] Adding api operation policy --- azurerm/config.go | 5 + azurerm/provider.go | 1 + ...arm_api_management_api_operation_policy.go | 170 ++++++++++++++ ...pi_management_api_operation_policy_test.go | 207 ++++++++++++++++++ website/azurerm.erb | 4 + ...agement_api_operation_policy.html.markdown | 63 ++++++ 6 files changed, 450 insertions(+) create mode 100644 azurerm/resource_arm_api_management_api_operation_policy.go create mode 100644 azurerm/resource_arm_api_management_api_operation_policy_test.go create mode 100644 website/docs/r/api_management_api_operation_policy.html.markdown diff --git a/azurerm/config.go b/azurerm/config.go index e846ff307bc4..c755312fa75a 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -133,6 +133,7 @@ type ArmClient struct { apiManagementApiClient apimanagement.APIClient apiManagementApiPoliciesClient apimanagement.APIPolicyClient apiManagementApiOperationsClient apimanagement.APIOperationClient + apiManagementApiOperationPoliciesClient apimanagement.APIOperationPolicyClient apiManagementApiSchemasClient apimanagement.APISchemaClient apiManagementApiVersionSetClient apimanagement.APIVersionSetClient apiManagementAuthorizationServersClient apimanagement.AuthorizationServerClient @@ -547,6 +548,10 @@ func (c *ArmClient) registerApiManagementServiceClients(endpoint, subscriptionId c.configureClient(&apiOperationsClient.Client, auth) c.apiManagementApiOperationsClient = apiOperationsClient + apiOperationPoliciesClient := apimanagement.NewAPIOperationPolicyClientWithBaseURI(endpoint, subscriptionId) + c.configureClient(&apiOperationPoliciesClient.Client, auth) + c.apiManagementApiOperationPoliciesClient = apiOperationPoliciesClient + apiSchemasClient := apimanagement.NewAPISchemaClientWithBaseURI(endpoint, subscriptionId) c.configureClient(&apiSchemasClient.Client, auth) c.apiManagementApiSchemasClient = apiSchemasClient diff --git a/azurerm/provider.go b/azurerm/provider.go index 7f0912177feb..de0333976bea 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -176,6 +176,7 @@ func Provider() terraform.ResourceProvider { "azurerm_api_management": resourceArmApiManagementService(), "azurerm_api_management_api": resourceArmApiManagementApi(), "azurerm_api_management_api_operation": resourceArmApiManagementApiOperation(), + "azurerm_api_management_api_operation_policy": resourceArmApiManagementApiOperationPolicy(), "azurerm_api_management_api_policy": resourceArmApiManagementApiPolicy(), "azurerm_api_management_api_schema": resourceArmApiManagementApiSchema(), "azurerm_api_management_api_version_set": resourceArmApiManagementApiVersionSet(), diff --git a/azurerm/resource_arm_api_management_api_operation_policy.go b/azurerm/resource_arm_api_management_api_operation_policy.go new file mode 100644 index 000000000000..97614735d00c --- /dev/null +++ b/azurerm/resource_arm_api_management_api_operation_policy.go @@ -0,0 +1,170 @@ +package azurerm + +import ( + "fmt" + "log" + + "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/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmApiManagementApiOperationPolicy() *schema.Resource { + return &schema.Resource{ + Create: resourceArmApiManagementAPIOperationPolicyCreateUpdate, + Read: resourceArmApiManagementAPIOperationPolicyRead, + Update: resourceArmApiManagementAPIOperationPolicyCreateUpdate, + Delete: resourceArmApiManagementAPIOperationPolicyDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "resource_group_name": resourceGroupNameSchema(), + + "api_management_name": azure.SchemaApiManagementName(), + + "api_name": azure.SchemaApiManagementChildName(), + + "operation_id": azure.SchemaApiManagementChildName(), + + "xml_content": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ConflictsWith: []string{"xml_link"}, + DiffSuppressFunc: suppress.XmlDiff, + }, + + "xml_link": { + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"xml_content"}, + }, + }, + } +} + +func resourceArmApiManagementAPIOperationPolicyCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementApiOperationPoliciesClient + ctx := meta.(*ArmClient).StopContext + + resourceGroup := d.Get("resource_group_name").(string) + serviceName := d.Get("api_management_name").(string) + apiName := d.Get("api_name").(string) + operationID := d.Get("operation_id").(string) + + if requireResourcesToBeImported && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, serviceName, apiName, operationID) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing API Operation Policy (API Management Service %q / API %q / Operation %q / Resource Group %q): %s", serviceName, apiName, operationID, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_api_management_api_operation_policy", *existing.ID) + } + } + + parameters := apimanagement.PolicyContract{} + + xmlContent := d.Get("xml_content").(string) + xmlLink := d.Get("xml_link").(string) + + if xmlContent != "" { + parameters.PolicyContractProperties = &apimanagement.PolicyContractProperties{ + ContentFormat: apimanagement.XML, + PolicyContent: utils.String(xmlContent), + } + } + + if xmlLink != "" { + parameters.PolicyContractProperties = &apimanagement.PolicyContractProperties{ + ContentFormat: apimanagement.XMLLink, + PolicyContent: utils.String(xmlLink), + } + } + + if parameters.PolicyContractProperties == nil { + return fmt.Errorf("Either `xml_content` or `xml_link` must be set") + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, serviceName, apiName, operationID, parameters, ""); err != nil { + return fmt.Errorf("Error creating or updating API Policy (Resource Group %q / API Management Service %q / API %q / Operation %q): %+v", resourceGroup, serviceName, apiName, operationID, err) + } + + resp, err := client.Get(ctx, resourceGroup, serviceName, apiName, operationID) + if err != nil { + return fmt.Errorf("Error retrieving API Policy (Resource Group %q / API Management Service %q / API %q / Operation %q): %+v", resourceGroup, serviceName, apiName, operationID, err) + } + if resp.ID == nil { + return fmt.Errorf("Cannot read ID for API Policy (Resource Group %q / API Management Service %q / API %q / Operation %q): %+v", resourceGroup, serviceName, apiName, operationID, err) + } + d.SetId(*resp.ID) + + return resourceArmApiManagementAPIOperationPolicyRead(d, meta) +} + +func resourceArmApiManagementAPIOperationPolicyRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementApiOperationPoliciesClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + serviceName := id.Path["service"] + apiName := id.Path["apis"] + operationID := id.Path["operations"] + + resp, err := client.Get(ctx, resourceGroup, serviceName, apiName, operationID) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] API Policy (Resource Group %q / API Management Service %q / API %q / Operation %q) was not found - removing from state!", resourceGroup, serviceName, apiName, operationID) + d.SetId("") + return nil + } + + return fmt.Errorf("Error making Read request for API Policy (Resource Group %q / API Management Service %q / API %q / Operation %q): %+v", resourceGroup, serviceName, apiName, operationID, err) + } + + d.Set("resource_group_name", resourceGroup) + d.Set("api_management_name", serviceName) + d.Set("api_name", apiName) + d.Set("operation_id", operationID) + + if properties := resp.PolicyContractProperties; properties != nil { + // when you submit an `xml_link` to the API, the API downloads this link and stores it as `xml_content` + // as such there is no way to set `xml_link` and we'll let Terraform handle it + d.Set("xml_content", properties.PolicyContent) + } + + return nil +} + +func resourceArmApiManagementAPIOperationPolicyDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementApiOperationPoliciesClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + serviceName := id.Path["service"] + apiName := id.Path["apis"] + operationID := id.Path["operations"] + + if resp, err := client.Delete(ctx, resourceGroup, serviceName, apiName, operationID, ""); err != nil { + if !utils.ResponseWasNotFound(resp) { + return fmt.Errorf("Error deleting API Policy (Resource Group %q / API Management Service %q / API %q / Operation %q): %+v", resourceGroup, serviceName, apiName, operationID, err) + } + } + + return nil +} diff --git a/azurerm/resource_arm_api_management_api_operation_policy_test.go b/azurerm/resource_arm_api_management_api_operation_policy_test.go new file mode 100644 index 000000000000..79dd16e10678 --- /dev/null +++ b/azurerm/resource_arm_api_management_api_operation_policy_test.go @@ -0,0 +1,207 @@ +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 TestAccAzureRMApiManagementAPIOperationPolicy_basic(t *testing.T) { + resourceName := "azurerm_api_management_api_operation_policy.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApiManagementAPIOperationPolicyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApiManagementAPIOperationPolicy_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementAPIOperationPolicyExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"xml_link"}, + }, + }, + }) +} + +func TestAccAzureRMApiManagementAPIOperationPolicy_requiresImport(t *testing.T) { + if !requireResourcesToBeImported { + t.Skip("Skipping since resources aren't required to be imported") + return + } + + resourceName := "azurerm_api_management_api_operation_policy.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApiManagementAPIOperationPolicyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApiManagementAPIOperationPolicy_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementAPIOperationPolicyExists(resourceName), + ), + }, + { + Config: testAccAzureRMApiManagementAPIOperationPolicy_requiresImport(ri, location), + ExpectError: testRequiresImportError("azurerm_api_management_api_policy"), + }, + }, + }) +} + +func TestAccAzureRMApiManagementAPIOperationPolicy_update(t *testing.T) { + resourceName := "azurerm_api_management_api_operation_policy.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApiManagementAPIOperationPolicyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApiManagementAPIOperationPolicy_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementAPIOperationPolicyExists(resourceName), + ), + }, + { + Config: testAccAzureRMApiManagementAPIOperationPolicy_updated(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementAPIOperationPolicyExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"xml_link"}, + }, + }, + }) +} + +func testCheckAzureRMApiManagementAPIOperationPolicyExists(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) + } + + apiName := rs.Primary.Attributes["api_name"] + serviceName := rs.Primary.Attributes["api_management_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + operationID := rs.Primary.Attributes["operation_id"] + + conn := testAccProvider.Meta().(*ArmClient).apiManagementApiOperationPoliciesClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + resp, err := conn.Get(ctx, resourceGroup, serviceName, apiName, operationID) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: API Policy (API Management Service %q / API %q / Operation %q / Resource Group %q) does not exist", serviceName, apiName, operationID, resourceGroup) + } + + return fmt.Errorf("Bad: Get on apiManagementAPIOperationPoliciesClient: %+v", err) + } + + return nil + } +} + +func testCheckAzureRMApiManagementAPIOperationPolicyDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).apiManagementApiOperationPoliciesClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_api_management_api_operation_policy" { + continue + } + + apiName := rs.Primary.Attributes["api_name"] + serviceName := rs.Primary.Attributes["api_management_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + operationID := rs.Primary.Attributes["operation_id"] + + ctx := testAccProvider.Meta().(*ArmClient).StopContext + resp, err := conn.Get(ctx, resourceGroup, serviceName, apiName, operationID) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return err + } + + return nil + } + + return nil +} + +func testAccAzureRMApiManagementAPIOperationPolicy_basic(rInt int, location string) string { + template := testAccAzureRMApiManagementApiOperation_basic(rInt, location) + + return fmt.Sprintf(` +%s + +resource "azurerm_api_management_api_operation_policy" "test" { + api_name = "${azurerm_api_management_api.test.name}" + api_management_name = "${azurerm_api_management.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + operation_id = "${azurerm_api_management_api_operation.test.operation_id}" + xml_link = "https://gist.githubusercontent.com/tombuildsstuff/4f58581599d2c9f64b236f505a361a67/raw/0d29dcb0167af1e5afe4bd52a6d7f69ba1e05e1f/example.xml" +} +`, template) +} + +func testAccAzureRMApiManagementAPIOperationPolicy_requiresImport(rInt int, location string) string { + template := testAccAzureRMApiManagementAPIOperationPolicy_basic(rInt, location) + return fmt.Sprintf(` +%s + +resource "azurerm_api_management_api_operation_policy" "import" { + api_name = "${azurerm_api_management_api_policy.test.api_name}" + api_management_name = "${azurerm_api_management_api_policy.test.api_management_name}" + resource_group_name = "${azurerm_api_management_api_policy.test.resource_group_name}" + operation_id = "${azurerm_api_management_api_operation.test.operation_id}" + xml_link = "${azurerm_api_management_api_policy.test.xml_link}" +} +`, template) +} + +func testAccAzureRMApiManagementAPIOperationPolicy_updated(rInt int, location string) string { + template := testAccAzureRMApiManagementApiOperation_basic(rInt, location) + return fmt.Sprintf(` +%s + +resource "azurerm_api_management_api_operation_policy" "test" { + api_name = "${azurerm_api_management_api.test.name}" + api_management_name = "${azurerm_api_management.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + operation_id = "${azurerm_api_management_api_operation.test.operation_id}" + xml_content = < + + + + +XML +} +`, template) +} diff --git a/website/azurerm.erb b/website/azurerm.erb index baf93df4e484..c10c46e10250 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -366,6 +366,10 @@ azurerm_api_management_api_operation + > + azurerm_api_management_api_operation_policy + + > azurerm_api_management_api_policy diff --git a/website/docs/r/api_management_api_operation_policy.html.markdown b/website/docs/r/api_management_api_operation_policy.html.markdown new file mode 100644 index 000000000000..153d8a4579e6 --- /dev/null +++ b/website/docs/r/api_management_api_operation_policy.html.markdown @@ -0,0 +1,63 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_api_management_api_operation_policy" +sidebar_current: "docs-azurerm-resource-api-management-api-operation-policy" +description: |- + Manages an API Management API Operation Policy +--- + +# azurerm_api_management_api_operation_policy + +Manages an API Management API Operation Policy + + +## Example Usage + +```hcl +resource "azurerm_api_management_api_operation" "example" { + ... +} + +resource "azurerm_api_management_api_policy" "example" { + api_name = "${azurerm_api_management_api_operation.example.api_name}" + api_management_name = "${azurerm_api_management_api_operation.example.api_management_name}" + resource_group_name = "${azurerm_api_management_api_operation.example.resource_group_name}" + operation_id = "${azurerm_api_management_api_operation.example.operation_id}" + xml_content = < + + + + +XML +} +``` + + +## Argument Reference + +The following arguments are supported: + +* `api_name` - (Required) The ID of the API Management API Operation 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. + +* `xml_content` - (Optional) The XML Content for this Policy. + +* `xml_link` - (Optional) A link to a Policy XML Document, which must be publicly available. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The ID of the API Management API Operation Policy. + +## Import + +API Management API Operation Policy can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_api_management_api_operation_policy.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.ApiManagement/service/instance1/apis/api1/operations/operation1/policies/policy +``` From f22c9080f3a2e1565fb103495cc383bc7b660304 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Fri, 3 May 2019 09:15:13 -0600 Subject: [PATCH 4/5] Updating error messages --- ...source_arm_api_management_api_operation_policy.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/azurerm/resource_arm_api_management_api_operation_policy.go b/azurerm/resource_arm_api_management_api_operation_policy.go index 97614735d00c..be26c62d1727 100644 --- a/azurerm/resource_arm_api_management_api_operation_policy.go +++ b/azurerm/resource_arm_api_management_api_operation_policy.go @@ -94,15 +94,15 @@ func resourceArmApiManagementAPIOperationPolicyCreateUpdate(d *schema.ResourceDa } if _, err := client.CreateOrUpdate(ctx, resourceGroup, serviceName, apiName, operationID, parameters, ""); err != nil { - return fmt.Errorf("Error creating or updating API Policy (Resource Group %q / API Management Service %q / API %q / Operation %q): %+v", resourceGroup, serviceName, apiName, operationID, err) + return fmt.Errorf("Error creating or updating API Operation Policy (Resource Group %q / API Management Service %q / API %q / Operation %q): %+v", resourceGroup, serviceName, apiName, operationID, err) } resp, err := client.Get(ctx, resourceGroup, serviceName, apiName, operationID) if err != nil { - return fmt.Errorf("Error retrieving API Policy (Resource Group %q / API Management Service %q / API %q / Operation %q): %+v", resourceGroup, serviceName, apiName, operationID, err) + return fmt.Errorf("Error retrieving API Operation Policy (Resource Group %q / API Management Service %q / API %q / Operation %q): %+v", resourceGroup, serviceName, apiName, operationID, err) } if resp.ID == nil { - return fmt.Errorf("Cannot read ID for API Policy (Resource Group %q / API Management Service %q / API %q / Operation %q): %+v", resourceGroup, serviceName, apiName, operationID, err) + return fmt.Errorf("Cannot read ID for API Operation Policy (Resource Group %q / API Management Service %q / API %q / Operation %q): %+v", resourceGroup, serviceName, apiName, operationID, err) } d.SetId(*resp.ID) @@ -125,12 +125,12 @@ func resourceArmApiManagementAPIOperationPolicyRead(d *schema.ResourceData, meta resp, err := client.Get(ctx, resourceGroup, serviceName, apiName, operationID) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[DEBUG] API Policy (Resource Group %q / API Management Service %q / API %q / Operation %q) was not found - removing from state!", resourceGroup, serviceName, apiName, operationID) + log.Printf("[DEBUG] API Operation Policy (Resource Group %q / API Management Service %q / API %q / Operation %q) was not found - removing from state!", resourceGroup, serviceName, apiName, operationID) d.SetId("") return nil } - return fmt.Errorf("Error making Read request for API Policy (Resource Group %q / API Management Service %q / API %q / Operation %q): %+v", resourceGroup, serviceName, apiName, operationID, err) + return fmt.Errorf("Error making Read request for API Operation Policy (Resource Group %q / API Management Service %q / API %q / Operation %q): %+v", resourceGroup, serviceName, apiName, operationID, err) } d.Set("resource_group_name", resourceGroup) @@ -162,7 +162,7 @@ func resourceArmApiManagementAPIOperationPolicyDelete(d *schema.ResourceData, me if resp, err := client.Delete(ctx, resourceGroup, serviceName, apiName, operationID, ""); err != nil { if !utils.ResponseWasNotFound(resp) { - return fmt.Errorf("Error deleting API Policy (Resource Group %q / API Management Service %q / API %q / Operation %q): %+v", resourceGroup, serviceName, apiName, operationID, err) + return fmt.Errorf("Error deleting API Operation Policy (Resource Group %q / API Management Service %q / API %q / Operation %q): %+v", resourceGroup, serviceName, apiName, operationID, err) } } From 4e779fe747ce2fbf6c9a1157c954f2f55a12b840 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Sat, 4 May 2019 10:59:42 +0100 Subject: [PATCH 5/5] Update website/docs/r/api_management_api_operation_policy.html.markdown --- .../docs/r/api_management_api_operation_policy.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/api_management_api_operation_policy.html.markdown b/website/docs/r/api_management_api_operation_policy.html.markdown index 153d8a4579e6..98b0f7a8ac72 100644 --- a/website/docs/r/api_management_api_operation_policy.html.markdown +++ b/website/docs/r/api_management_api_operation_policy.html.markdown @@ -18,7 +18,7 @@ resource "azurerm_api_management_api_operation" "example" { ... } -resource "azurerm_api_management_api_policy" "example" { +resource "azurerm_api_management_api_operation_policy" "example" { api_name = "${azurerm_api_management_api_operation.example.api_name}" api_management_name = "${azurerm_api_management_api_operation.example.api_management_name}" resource_group_name = "${azurerm_api_management_api_operation.example.resource_group_name}"