diff --git a/azurerm/config.go b/azurerm/config.go index 8b0a069070eb..edfdeae367ab 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -132,6 +132,7 @@ type ArmClient struct { // API Management apiManagementApiClient apimanagement.APIClient apiManagementApiOperationsClient apimanagement.APIOperationClient + apiManagementApiSchemasClient apimanagement.APISchemaClient apiManagementApiVersionSetClient apimanagement.APIVersionSetClient apiManagementAuthorizationServersClient apimanagement.AuthorizationServerClient apiManagementCertificatesClient apimanagement.CertificateClient @@ -541,6 +542,10 @@ func (c *ArmClient) registerApiManagementServiceClients(endpoint, subscriptionId c.configureClient(&apiOperationsClient.Client, auth) c.apiManagementApiOperationsClient = apiOperationsClient + apiSchemasClient := apimanagement.NewAPISchemaClientWithBaseURI(endpoint, subscriptionId) + c.configureClient(&apiSchemasClient.Client, auth) + c.apiManagementApiSchemasClient = apiSchemasClient + apiVersionSetClient := apimanagement.NewAPIVersionSetClientWithBaseURI(endpoint, subscriptionId) c.configureClient(&apiVersionSetClient.Client, auth) c.apiManagementApiVersionSetClient = apiVersionSetClient diff --git a/azurerm/provider.go b/azurerm/provider.go index 60eeed2e8886..347b0eec675d 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_schema": resourceArmApiManagementApiSchema(), "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_schema.go b/azurerm/resource_arm_api_management_api_schema.go new file mode 100644 index 000000000000..d8936aba4d5b --- /dev/null +++ b/azurerm/resource_arm_api_management_api_schema.go @@ -0,0 +1,157 @@ +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/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmApiManagementApiSchema() *schema.Resource { + return &schema.Resource{ + Create: resourceArmApiManagementApiSchemaCreateUpdate, + Read: resourceArmApiManagementApiSchemaRead, + Update: resourceArmApiManagementApiSchemaCreateUpdate, + Delete: resourceArmApiManagementApiSchemaDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "schema_id": azure.SchemaApiManagementChildName(), + + "api_name": azure.SchemaApiManagementChildName(), + + "resource_group_name": resourceGroupNameSchema(), + + "api_management_name": azure.SchemaApiManagementName(), + + "content_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, + }, + + "value": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, + }, + }, + } +} + +func resourceArmApiManagementApiSchemaCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementApiSchemasClient + ctx := meta.(*ArmClient).StopContext + + schemaID := d.Get("schema_id").(string) + 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, schemaID) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing API Schema %q (API Management Service %q / API %q / Resource Group %q): %s", schemaID, serviceName, apiName, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_api_management_api_schema", *existing.ID) + } + } + + contentType := d.Get("content_type").(string) + value := d.Get("value").(string) + parameters := apimanagement.SchemaContract{ + SchemaContractProperties: &apimanagement.SchemaContractProperties{ + ContentType: &contentType, + SchemaDocumentProperties: &apimanagement.SchemaDocumentProperties{ + Value: &value, + }, + }, + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, serviceName, apiName, schemaID, parameters, ""); err != nil { + return fmt.Errorf("Error creating or updating API Schema %q (API Management Service %q / API %q / Resource Group %q): %s", schemaID, serviceName, apiName, resourceGroup, err) + } + + resp, err := client.Get(ctx, resourceGroup, serviceName, apiName, schemaID) + if err != nil { + return fmt.Errorf("Error retrieving API Schema %q (API Management Service %q / API %q / Resource Group %q): %s", schemaID, serviceName, apiName, resourceGroup, err) + } + if resp.ID == nil { + return fmt.Errorf("Cannot read ID for API Schema %q (API Management Service %q / API %q / Resource Group %q): %s", schemaID, serviceName, apiName, resourceGroup, err) + } + d.SetId(*resp.ID) + + return resourceArmApiManagementApiSchemaRead(d, meta) +} + +func resourceArmApiManagementApiSchemaRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementApiSchemasClient + 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"] + schemaID := id.Path["schemas"] + + resp, err := client.Get(ctx, resourceGroup, serviceName, apiName, schemaID) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] API Schema %q (API Management Service %q / API %q / Resource Group %q) was not found - removing from state!", schemaID, serviceName, apiName, resourceGroup) + d.SetId("") + return nil + } + + return fmt.Errorf("Error making Read request for API Schema %q (API Management Service %q / API %q / Resource Group %q): %s", schemaID, serviceName, apiName, resourceGroup, err) + } + + d.Set("resource_group_name", resourceGroup) + d.Set("api_management_name", serviceName) + d.Set("api_name", apiName) + d.Set("schema_id", schemaID) + + if properties := resp.SchemaContractProperties; properties != nil { + d.Set("content_type", properties.ContentType) + if documentProperties := properties.SchemaDocumentProperties; documentProperties != nil { + d.Set("value", documentProperties.Value) + } + } + + return nil +} + +func resourceArmApiManagementApiSchemaDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).apiManagementApiSchemasClient + 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"] + schemaID := id.Path["schemas"] + + if resp, err := client.Delete(ctx, resourceGroup, serviceName, apiName, schemaID, ""); err != nil { + if !utils.ResponseWasNotFound(resp) { + return fmt.Errorf("Error deleting API Schema %q (API Management Service %q / API %q / Resource Group %q): %s", schemaID, serviceName, apiName, resourceGroup, err) + } + } + + return nil +} diff --git a/azurerm/resource_arm_api_management_api_schema_test.go b/azurerm/resource_arm_api_management_api_schema_test.go new file mode 100644 index 000000000000..06a27d7411ac --- /dev/null +++ b/azurerm/resource_arm_api_management_api_schema_test.go @@ -0,0 +1,187 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMApiManagementApiSchema_basic(t *testing.T) { + resourceName := "azurerm_api_management_api_schema.test" + ri := acctest.RandInt() + location := testLocation() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApiManagementApiSchemaDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApiManagementApiSchema_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementApiSchemaExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMApiManagementApiSchema_requiresImport(t *testing.T) { + if !requireResourcesToBeImported { + t.Skip("Skipping since resources aren't required to be imported") + return + } + + resourceName := "azurerm_api_management_api_schema.test" + ri := acctest.RandInt() + location := testLocation() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApiManagementApiSchemaDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApiManagementApiSchema_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApiManagementApiSchemaExists(resourceName), + ), + }, + { + Config: testAccAzureRMApiManagementApiSchema_requiresImport(ri, location), + ExpectError: testRequiresImportError("azurerm_api_management_api_schema"), + }, + }, + }) +} + +func testCheckAzureRMApiManagementApiSchemaDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).apiManagementApiSchemasClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_api_management_api_schema" { + continue + } + + schemaID := rs.Primary.Attributes["schema_id"] + apiName := rs.Primary.Attributes["api_name"] + serviceName := rs.Primary.Attributes["api_management_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := conn.Get(ctx, resourceGroup, serviceName, apiName, schemaID) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return err + } + + return nil + } + + return nil +} + +func testCheckAzureRMApiManagementApiSchemaExists(name 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[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + schemaID := rs.Primary.Attributes["schema_id"] + apiName := rs.Primary.Attributes["api_name"] + serviceName := rs.Primary.Attributes["api_management_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + conn := testAccProvider.Meta().(*ArmClient).apiManagementApiSchemasClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + resp, err := conn.Get(ctx, resourceGroup, serviceName, apiName, schemaID) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: API Schema %q (API %q / API Management Service %q / Resource Group: %q) does not exist", schemaID, apiName, serviceName, resourceGroup) + } + + return fmt.Errorf("Bad: Get on apiManagementApiSchemasClient: %+v", err) + } + + return nil + } +} + +func testAccAzureRMApiManagementApiSchema_basic(rInt int, location string) string { + template := testAccAzureRMApiManagementApiSchema_template(rInt, location) + return fmt.Sprintf(` +%s + +resource "azurerm_api_management_api_schema" "test" { + api_name = "${azurerm_api_management_api.test.name}" + api_management_name = "${azurerm_api_management_api.test.api_management_name}" + resource_group_name = "${azurerm_api_management_api.test.resource_group_name}" + schema_id = "acctestSchema%d" + content_type = "application/vnd.ms-azure-apim.xsd+xml" + value = "${file("testdata/api_management_api_schema.xml")}" +} +`, template, rInt) +} + +func testAccAzureRMApiManagementApiSchema_requiresImport(rInt int, location string) string { + template := testAccAzureRMApiManagementApiSchema_template(rInt, location) + return fmt.Sprintf(` +%s + +resource "azurerm_api_management_api_schema" "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}" + schema_id = "acctestSchema%d" + content_type = "application/vnd.ms-azure-apim.xsd+xml" + value = "${file("testdata/api_management_api_schema.xml")}" +} +`, template, rInt) +} + +func testAccAzureRMApiManagementApiSchema_template(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" +} +`, rInt, location, rInt, rInt) +} diff --git a/azurerm/testdata/api_management_api_schema.xml b/azurerm/testdata/api_management_api_schema.xml new file mode 100644 index 000000000000..60aeede7d58f --- /dev/null +++ b/azurerm/testdata/api_management_api_schema.xml @@ -0,0 +1 @@ +\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n diff --git a/website/azurerm.erb b/website/azurerm.erb index d1f74c33bfc8..f8fdf7148599 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -365,6 +365,10 @@ > azurerm_api_management_api_operation + + > + azurerm_api_management_api_schema + > azurerm_api_management_version_set diff --git a/website/docs/r/api_management_api_schema.html.markdown b/website/docs/r/api_management_api_schema.html.markdown new file mode 100644 index 000000000000..487730228330 --- /dev/null +++ b/website/docs/r/api_management_api_schema.html.markdown @@ -0,0 +1,62 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_api_management_api_schema" +sidebar_current: "docs-azurerm-resource-api-management-api-schema" +description: |- + Manages an API Schema within an API Management Service. +--- + +# azurerm_api_management_api_schema + +Manages an API Schema within an API Management Service. + +## Example Usage + +```hcl +data "azurerm_api_management_api" "example" { + name = "search-api" + api_management_name = "search-api-management" + resource_group_name = "search-service" + revision = "2" +} + +resource "azurerm_api_management_api_schema" "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}" + schema_id = "example-sche,a" + content_type = "application/vnd.ms-azure-apim.xsd+xml" + value = "${file("api_management_api_schema.xml")}" +} + +``` + +## Argument Reference + +The following arguments are supported: + +* `schema_id` - (Required) A unique identifier for this API Schema. Changing this forces a new resource to be created. + +* `api_name` - (Required) The name of the API within the API Management Service where this API Schema should be created. Changing this forces a new resource to be created. + +* `api_management_name` - (Required) The Name of the API Management Service where the API exists. 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. + +* `content_type` - (Required) The content type of the API Schema. + +* `value` - (Required) The JSON escaped string defining the document representing the Schema. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The ID of the API Management API Schema. + +## Import + +API Management API Schema's can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_api_management_api_schema.test /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.ApiManagement/service/instance1/schemas/schema1 +```