From 58c52eec10f47bffc785ac7ee0de31b54c2066ee Mon Sep 17 00:00:00 2001 From: xuzhang3 <57888764+xuzhang3@users.noreply.github.com> Date: Wed, 7 Sep 2022 00:49:01 +0800 Subject: [PATCH] New Resource: `azurerm_api_management_api_tag_description` support config API tag description (#17876) Co-authored-by: xuzhang3 --- ...management_api_tag_description_resource.go | 162 ++++++++++++++++++ ...ement_api_tag_description_resource_test.go | 138 +++++++++++++++ .../services/apimanagement/client/client.go | 5 + .../parse/api_tag_descriptions.go | 81 +++++++++ .../parse/api_tag_descriptions_test.go | 144 ++++++++++++++++ .../services/apimanagement/registration.go | 1 + .../services/apimanagement/resourceids.go | 1 + .../validate/api_tag_descriptions_id.go | 23 +++ .../validate/api_tag_descriptions_id_test.go | 100 +++++++++++ ...nagement_api_tag_description.html.markdown | 102 +++++++++++ 10 files changed, 757 insertions(+) create mode 100644 internal/services/apimanagement/api_management_api_tag_description_resource.go create mode 100644 internal/services/apimanagement/api_management_api_tag_description_resource_test.go create mode 100644 internal/services/apimanagement/parse/api_tag_descriptions.go create mode 100644 internal/services/apimanagement/parse/api_tag_descriptions_test.go create mode 100644 internal/services/apimanagement/validate/api_tag_descriptions_id.go create mode 100644 internal/services/apimanagement/validate/api_tag_descriptions_id_test.go create mode 100644 website/docs/r/api_management_api_tag_description.html.markdown diff --git a/internal/services/apimanagement/api_management_api_tag_description_resource.go b/internal/services/apimanagement/api_management_api_tag_description_resource.go new file mode 100644 index 000000000000..2bc6d1072f91 --- /dev/null +++ b/internal/services/apimanagement/api_management_api_tag_description_resource.go @@ -0,0 +1,162 @@ +package apimanagement + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/apimanagement/mgmt/2021-08-01/apimanagement" + "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/apimanagement/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/apimanagement/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" + "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +func resourceApiManagementApiTagDescription() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Create: resourceApiManagementApiTagDescriptionCreateUpdate, + Read: resourceApiManagementApiTagDescriptionRead, + Update: resourceApiManagementApiTagDescriptionCreateUpdate, + Delete: resourceApiManagementApiTagDescriptionDelete, + + Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { + _, err := parse.ApiTagDescriptionsID(id) + return err + }), + + Timeouts: &pluginsdk.ResourceTimeout{ + Create: pluginsdk.DefaultTimeout(30 * time.Minute), + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + Update: pluginsdk.DefaultTimeout(30 * time.Minute), + Delete: pluginsdk.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*pluginsdk.Schema{ + + "api_tag_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ApiTagID, + }, + + "description": { + Type: pluginsdk.TypeString, + Optional: true, + }, + + "external_documentation_url": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.IsURLWithHTTPorHTTPS, + }, + + "external_documentation_description": { + Type: pluginsdk.TypeString, + Optional: true, + }, + }, + } +} + +func resourceApiManagementApiTagDescriptionCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).ApiManagement.ApiTagDescriptionClient + + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + apiTagId, err := parse.ApiTagID(d.Get("api_tag_id").(string)) + if err != nil { + return fmt.Errorf("parsing `api_id`: %v", err) + } + + id := parse.NewApiTagDescriptionsID(apiTagId.SubscriptionId, apiTagId.ResourceGroup, apiTagId.ServiceName, apiTagId.ApiName, apiTagId.TagName) + + if d.IsNewResource() { + existing, err := client.Get(ctx, id.ResourceGroup, id.ServiceName, id.ApiName, id.TagDescriptionName) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("checking for presence of existing %s: %s", id, err) + } + } + + if !utils.ResponseWasNotFound(existing.Response) { + return tf.ImportAsExistsError("azurerm_api_management_api_tag_description", id.ID()) + } + } + + tagDescParameter := apimanagement.TagDescriptionCreateParameters{TagDescriptionBaseProperties: &apimanagement.TagDescriptionBaseProperties{}} + if v, ok := d.GetOk("description"); ok { + tagDescParameter.Description = utils.String(v.(string)) + } + + if v, ok := d.GetOk("external_documentation_url"); ok { + tagDescParameter.ExternalDocsURL = utils.String(v.(string)) + } + + if v, ok := d.GetOk("external_documentation_description"); ok { + tagDescParameter.ExternalDocsDescription = utils.String(v.(string)) + } + + if _, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.ServiceName, id.ApiName, id.TagDescriptionName, tagDescParameter, ""); err != nil { + return fmt.Errorf("creating/updating %s: %+v", id, err) + } + + d.SetId(id.ID()) + + return resourceApiManagementApiTagDescriptionRead(d, meta) +} + +func resourceApiManagementApiTagDescriptionRead(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).ApiManagement.ApiTagDescriptionClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.ApiTagDescriptionsID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.ServiceName, id.ApiName, id.TagDescriptionName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] %s was not found - removing from state!", *id) + d.SetId("") + return nil + } + return fmt.Errorf("retrieving %s: %+v", *id, err) + } + + apiTagId := parse.NewApiTagID(id.SubscriptionId, id.ResourceGroup, id.ServiceName, id.ApiName, id.TagDescriptionName) + + d.Set("api_tag_id", apiTagId.ID()) + d.Set("description", resp.Description) + d.Set("external_documentation_url", resp.ExternalDocsURL) + d.Set("external_documentation_description", resp.ExternalDocsDescription) + + return nil +} + +func resourceApiManagementApiTagDescriptionDelete(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).ApiManagement.ApiTagDescriptionClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.ApiTagDescriptionsID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Delete(ctx, id.ResourceGroup, id.ServiceName, id.ApiName, id.TagDescriptionName, "") + if err != nil { + if !utils.ResponseWasNotFound(resp) { + return fmt.Errorf("deleting %s: %+v", *id, err) + } + } + + return nil +} diff --git a/internal/services/apimanagement/api_management_api_tag_description_resource_test.go b/internal/services/apimanagement/api_management_api_tag_description_resource_test.go new file mode 100644 index 000000000000..3dfde11b93d1 --- /dev/null +++ b/internal/services/apimanagement/api_management_api_tag_description_resource_test.go @@ -0,0 +1,138 @@ +package apimanagement_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/apimanagement/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type ApiManagementApiTagDescriptionResource struct{} + +func TestAccApiManagementApiTagDescription_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_api_management_api_tag_description", "test") + r := ApiManagementApiTagDescriptionResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccApiManagementApiTagDescription_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_api_management_api_tag_description", "test") + r := ApiManagementApiTagDescriptionResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImport), + }) +} + +func TestAccApiManagementApiTagDescription_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_api_management_api_tag_description", "test") + r := ApiManagementApiTagDescriptionResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.update(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func (ApiManagementApiTagDescriptionResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := parse.ApiTagDescriptionsID(state.ID) + if err != nil { + return nil, err + } + + resp, err := clients.ApiManagement.ApiTagDescriptionClient.Get(ctx, id.ResourceGroup, id.ServiceName, id.ApiName, id.TagDescriptionName) + if err != nil { + return nil, fmt.Errorf("reading %q: %+v", id, err) + } + + return utils.Bool(resp.ID != nil), nil +} + +func (r ApiManagementApiTagDescriptionResource) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +%s +resource "azurerm_api_management_tag" "test" { + api_management_id = azurerm_api_management.test.id + name = "acctest-Tag-%d" +} + +resource "azurerm_api_management_api_tag" "test" { + api_id = azurerm_api_management_api.test.id + name = "acctest-Tag-%d" +} + +resource "azurerm_api_management_api_tag_description" "test" { + api_tag_id = azurerm_api_management_api_tag.test.id + description = "tag description" + external_documentation_url = "https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs" + external_documentation_description = "external tag description" +} +`, ApiManagementApiResource{}.basic(data), data.RandomInteger, data.RandomInteger) +} + +func (r ApiManagementApiTagDescriptionResource) requiresImport(data acceptance.TestData) string { + return fmt.Sprintf(` +%s +resource "azurerm_api_management_api_tag_description" "import" { + api_tag_id = azurerm_api_management_api_tag_description.test.api_tag_id + description = azurerm_api_management_api_tag_description.test.description + external_documentation_url = azurerm_api_management_api_tag_description.test.external_documentation_url + external_documentation_description = azurerm_api_management_api_tag_description.test.external_documentation_description +} +`, r.basic(data)) +} + +func (r ApiManagementApiTagDescriptionResource) update(data acceptance.TestData) string { + return fmt.Sprintf(` +%s +resource "azurerm_api_management_tag" "test" { + api_management_id = azurerm_api_management.test.id + name = "acctest-Tag-%d" +} + +resource "azurerm_api_management_api_tag" "test" { + api_id = azurerm_api_management_api.test.id + name = "acctest-Tag-%d" +} + +resource "azurerm_api_management_api_tag_description" "test" { + api_tag_id = azurerm_api_management_api_tag.test.id + description = "tag description update" + external_documentation_url = "https://registry.terraform.io/providers/hashicorp/azurerm" + external_documentation_description = "external tag description update" +} +`, ApiManagementApiResource{}.basic(data), data.RandomInteger, data.RandomInteger) +} diff --git a/internal/services/apimanagement/client/client.go b/internal/services/apimanagement/client/client.go index 15b2d7af455b..c312c4a10d38 100644 --- a/internal/services/apimanagement/client/client.go +++ b/internal/services/apimanagement/client/client.go @@ -15,6 +15,7 @@ type Client struct { ApiReleasesClient *apimanagement.APIReleaseClient ApiSchemasClient *apimanagement.APISchemaClient ApiVersionSetClient *apimanagement.APIVersionSetClient + ApiTagDescriptionClient *apimanagement.APITagDescriptionClient AuthorizationServersClient *apimanagement.AuthorizationServerClient BackendClient *apimanagement.BackendClient CacheClient *apimanagement.CacheClient @@ -74,6 +75,9 @@ func NewClient(o *common.ClientOptions) *Client { apiVersionSetClient := apimanagement.NewAPIVersionSetClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&apiVersionSetClient.Client, o.ResourceManagerAuthorizer) + apiTagDescriptionClient := apimanagement.NewAPITagDescriptionClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&apiTagDescriptionClient.Client, o.ResourceManagerAuthorizer) + authorizationServersClient := apimanagement.NewAuthorizationServerClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&authorizationServersClient.Client, o.ResourceManagerAuthorizer) @@ -179,6 +183,7 @@ func NewClient(o *common.ClientOptions) *Client { ApiReleasesClient: &apiReleasesClient, ApiSchemasClient: &apiSchemasClient, ApiVersionSetClient: &apiVersionSetClient, + ApiTagDescriptionClient: &apiTagDescriptionClient, AuthorizationServersClient: &authorizationServersClient, BackendClient: &backendClient, CacheClient: &cacheClient, diff --git a/internal/services/apimanagement/parse/api_tag_descriptions.go b/internal/services/apimanagement/parse/api_tag_descriptions.go new file mode 100644 index 000000000000..fe1d76c86dd6 --- /dev/null +++ b/internal/services/apimanagement/parse/api_tag_descriptions.go @@ -0,0 +1,81 @@ +package parse + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "fmt" + "strings" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +type ApiTagDescriptionsId struct { + SubscriptionId string + ResourceGroup string + ServiceName string + ApiName string + TagDescriptionName string +} + +func NewApiTagDescriptionsID(subscriptionId, resourceGroup, serviceName, apiName, tagDescriptionName string) ApiTagDescriptionsId { + return ApiTagDescriptionsId{ + SubscriptionId: subscriptionId, + ResourceGroup: resourceGroup, + ServiceName: serviceName, + ApiName: apiName, + TagDescriptionName: tagDescriptionName, + } +} + +func (id ApiTagDescriptionsId) String() string { + segments := []string{ + fmt.Sprintf("Tag Description Name %q", id.TagDescriptionName), + fmt.Sprintf("Api Name %q", id.ApiName), + fmt.Sprintf("Service Name %q", id.ServiceName), + fmt.Sprintf("Resource Group %q", id.ResourceGroup), + } + segmentsStr := strings.Join(segments, " / ") + return fmt.Sprintf("%s: (%s)", "Api Tag Descriptions", segmentsStr) +} + +func (id ApiTagDescriptionsId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.ApiManagement/service/%s/apis/%s/tagDescriptions/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.ServiceName, id.ApiName, id.TagDescriptionName) +} + +// ApiTagDescriptionsID parses a ApiTagDescriptions ID into an ApiTagDescriptionsId struct +func ApiTagDescriptionsID(input string) (*ApiTagDescriptionsId, error) { + id, err := resourceids.ParseAzureResourceID(input) + if err != nil { + return nil, err + } + + resourceId := ApiTagDescriptionsId{ + SubscriptionId: id.SubscriptionID, + ResourceGroup: id.ResourceGroup, + } + + if resourceId.SubscriptionId == "" { + return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + } + + if resourceId.ResourceGroup == "" { + return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + } + + if resourceId.ServiceName, err = id.PopSegment("service"); err != nil { + return nil, err + } + if resourceId.ApiName, err = id.PopSegment("apis"); err != nil { + return nil, err + } + if resourceId.TagDescriptionName, err = id.PopSegment("tagDescriptions"); err != nil { + return nil, err + } + + if err := id.ValidateNoEmptySegments(input); err != nil { + return nil, err + } + + return &resourceId, nil +} diff --git a/internal/services/apimanagement/parse/api_tag_descriptions_test.go b/internal/services/apimanagement/parse/api_tag_descriptions_test.go new file mode 100644 index 000000000000..d28737c3c3a1 --- /dev/null +++ b/internal/services/apimanagement/parse/api_tag_descriptions_test.go @@ -0,0 +1,144 @@ +package parse + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "testing" + + "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" +) + +var _ resourceids.Id = ApiTagDescriptionsId{} + +func TestApiTagDescriptionsIDFormatter(t *testing.T) { + actual := NewApiTagDescriptionsID("12345678-1234-9876-4563-123456789012", "resGroup1", "service1", "api1", "tagDescriptionId1").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/apis/api1/tagDescriptions/tagDescriptionId1" + if actual != expected { + t.Fatalf("Expected %q but got %q", expected, actual) + } +} + +func TestApiTagDescriptionsID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *ApiTagDescriptionsId + }{ + + { + // empty + Input: "", + Error: true, + }, + + { + // missing SubscriptionId + Input: "/", + Error: true, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Error: true, + }, + + { + // missing ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", + Error: true, + }, + + { + // missing value for ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", + Error: true, + }, + + { + // missing ServiceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/", + Error: true, + }, + + { + // missing value for ServiceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/", + Error: true, + }, + + { + // missing ApiName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/", + Error: true, + }, + + { + // missing value for ApiName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/apis/", + Error: true, + }, + + { + // missing TagDescriptionName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/apis/api1/", + Error: true, + }, + + { + // missing value for TagDescriptionName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/apis/api1/tagDescriptions/", + Error: true, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/apis/api1/tagDescriptions/tagDescriptionId1", + Expected: &ApiTagDescriptionsId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroup: "resGroup1", + ServiceName: "service1", + ApiName: "api1", + TagDescriptionName: "tagDescriptionId1", + }, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.APIMANAGEMENT/SERVICE/SERVICE1/APIS/API1/TAGDESCRIPTIONS/TAGDESCRIPTIONID1", + Error: true, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := ApiTagDescriptionsID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %s", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + if actual.ResourceGroup != v.Expected.ResourceGroup { + t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + } + if actual.ServiceName != v.Expected.ServiceName { + t.Fatalf("Expected %q but got %q for ServiceName", v.Expected.ServiceName, actual.ServiceName) + } + if actual.ApiName != v.Expected.ApiName { + t.Fatalf("Expected %q but got %q for ApiName", v.Expected.ApiName, actual.ApiName) + } + if actual.TagDescriptionName != v.Expected.TagDescriptionName { + t.Fatalf("Expected %q but got %q for TagDescriptionName", v.Expected.TagDescriptionName, actual.TagDescriptionName) + } + } +} diff --git a/internal/services/apimanagement/registration.go b/internal/services/apimanagement/registration.go index 512145362ced..0ae0f67da27e 100644 --- a/internal/services/apimanagement/registration.go +++ b/internal/services/apimanagement/registration.go @@ -51,6 +51,7 @@ func (r Registration) SupportedResources() map[string]*pluginsdk.Resource { "azurerm_api_management_api_release": resourceApiManagementApiRelease(), "azurerm_api_management_api_schema": resourceApiManagementApiSchema(), "azurerm_api_management_api_tag": resourceApiManagementApiTag(), + "azurerm_api_management_api_tag_description": resourceApiManagementApiTagDescription(), "azurerm_api_management_api_version_set": resourceApiManagementApiVersionSet(), "azurerm_api_management_authorization_server": resourceApiManagementAuthorizationServer(), "azurerm_api_management_backend": resourceApiManagementBackend(), diff --git a/internal/services/apimanagement/resourceids.go b/internal/services/apimanagement/resourceids.go index 97413f289e84..4d42f97c3953 100644 --- a/internal/services/apimanagement/resourceids.go +++ b/internal/services/apimanagement/resourceids.go @@ -7,6 +7,7 @@ package apimanagement //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=ApiOperationPolicy -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/apis/api1/operations/operation1/policies/policy1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=ApiPolicy -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/apis/api1/policies/policy1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=ApiSchema -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/apis/api1/schemas/schema1 +//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=ApiTagDescriptions -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/apis/api1/tagDescriptions/tagDescriptionId1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=ApiVersionSet -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/apiVersionSets/apiVersionSet1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=AuthorizationServer -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/authorizationServers/authorizationserver1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=Backend -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/backends/backend1 diff --git a/internal/services/apimanagement/validate/api_tag_descriptions_id.go b/internal/services/apimanagement/validate/api_tag_descriptions_id.go new file mode 100644 index 000000000000..7f31eb3f24ec --- /dev/null +++ b/internal/services/apimanagement/validate/api_tag_descriptions_id.go @@ -0,0 +1,23 @@ +package validate + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "fmt" + + "github.com/hashicorp/terraform-provider-azurerm/internal/services/apimanagement/parse" +) + +func ApiTagDescriptionsID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := parse.ApiTagDescriptionsID(v); err != nil { + errors = append(errors, err) + } + + return +} diff --git a/internal/services/apimanagement/validate/api_tag_descriptions_id_test.go b/internal/services/apimanagement/validate/api_tag_descriptions_id_test.go new file mode 100644 index 000000000000..e1944c3c5b4c --- /dev/null +++ b/internal/services/apimanagement/validate/api_tag_descriptions_id_test.go @@ -0,0 +1,100 @@ +package validate + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import "testing" + +func TestApiTagDescriptionsID(t *testing.T) { + cases := []struct { + Input string + Valid bool + }{ + + { + // empty + Input: "", + Valid: false, + }, + + { + // missing SubscriptionId + Input: "/", + Valid: false, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Valid: false, + }, + + { + // missing ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", + Valid: false, + }, + + { + // missing value for ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", + Valid: false, + }, + + { + // missing ServiceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/", + Valid: false, + }, + + { + // missing value for ServiceName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/", + Valid: false, + }, + + { + // missing ApiName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/", + Valid: false, + }, + + { + // missing value for ApiName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/apis/", + Valid: false, + }, + + { + // missing TagDescriptionName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/apis/api1/", + Valid: false, + }, + + { + // missing value for TagDescriptionName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/apis/api1/tagDescriptions/", + Valid: false, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.ApiManagement/service/service1/apis/api1/tagDescriptions/tagDescriptionId1", + Valid: true, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.APIMANAGEMENT/SERVICE/SERVICE1/APIS/API1/TAGDESCRIPTIONS/TAGDESCRIPTIONID1", + Valid: false, + }, + } + for _, tc := range cases { + t.Logf("[DEBUG] Testing Value %s", tc.Input) + _, errors := ApiTagDescriptionsID(tc.Input, "test") + valid := len(errors) == 0 + + if tc.Valid != valid { + t.Fatalf("Expected %t but got %t", tc.Valid, valid) + } + } +} diff --git a/website/docs/r/api_management_api_tag_description.html.markdown b/website/docs/r/api_management_api_tag_description.html.markdown new file mode 100644 index 000000000000..f43e0ca88691 --- /dev/null +++ b/website/docs/r/api_management_api_tag_description.html.markdown @@ -0,0 +1,102 @@ +--- +subcategory: "API Management" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_api_management_api_tag_description" +description: |- + Manages an API Tag Description within an API Management Service. +--- + +# azurerm_api_management_api_tag_description + +Manages an API Tag Description within an API Management Service. + +## Example Usage + +```hcl +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_api_management" "example" { + name = "example-apim" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + publisher_name = "My Company" + publisher_email = "company@terraform.io" + + sku_name = "Developer_1" +} + +resource "azurerm_api_management_api" "example" { + name = "example-api" + resource_group_name = azurerm_resource_group.example.name + api_management_name = azurerm_api_management.example.name + revision = "1" + display_name = "Example API" + path = "example" + protocols = ["https"] + + import { + content_format = "swagger-link-json" + content_value = "http://conferenceapi.azurewebsites.net/?format=json" + } +} + +resource "azurerm_api_management_tag" "example" { + api_management_id = azurerm_api_management.example.id + name = "example-Tag" +} + +resource "azurerm_api_management_tag" "example" { + api_management_id = azurerm_api_management.example.id + name = "example-tag" +} + +resource "azurerm_api_management_api_tag_description" "example" { + api_tag_id = azurerm_api_management_tag.example.id + description = "This is an example description" + external_docs_url = "https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs" + external_docs_description = "This is an example external docs description" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `api_tag_id` - (Required) The The ID of the API Management API Tag. Changing this forces a new API Management API Tag Description to be created. + +* `description` - (Optional) The description of the Tag. + +* `external_documentation_url` - (Optional) The URL of external documentation resources describing the tag. + +* `external_documentation_description` - (Optional) The description of the external documentation resources describing the tag. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The ID of the API Management API Schema. + +## Timeouts + +The `timeouts` block allows you to +specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the API Management API Schema. +* `update` - (Defaults to 30 minutes) Used when updating the API Management API Schema. +* `read` - (Defaults to 5 minutes) Used when retrieving the API Management API Schema. +* `delete` - (Defaults to 30 minutes) Used when deleting 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_tag_description.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.ApiManagement/service/instance1/apis/api1/tagDescriptions/tagDescriptionId1 +```