Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api_management_api_operation_tag - Don't use this resource to create tags. Only attach existing tags to operations #27518

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ import (
"github.com/hashicorp/go-azure-sdk/resource-manager/apimanagement/2022-08-01/tag"
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
"github.com/hashicorp/terraform-provider-azurerm/internal/features"
"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"
)

func resourceApiManagementApiOperationTag() *pluginsdk.Resource {
return &pluginsdk.Resource{
Create: resourceApiManagementApiOperationTagCreateUpdate,
resource := &pluginsdk.Resource{
Create: resourceApiManagementApiOperationTagCreate,
Read: resourceApiManagementApiOperationTagRead,
Update: resourceApiManagementApiOperationTagCreateUpdate,
Update: resourceApiManagementApiOperationTagUpdate,
Delete: resourceApiManagementApiOperationTagDelete,

Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error {
Expand Down Expand Up @@ -52,17 +52,22 @@ func resourceApiManagementApiOperationTag() *pluginsdk.Resource {
ForceNew: true,
ValidateFunc: validate.ApiManagementChildName,
},

"display_name": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringIsNotEmpty,
},
},
}

if !features.FivePointOhBeta() {
resource.Schema["display_name"] = &pluginsdk.Schema{
Type: pluginsdk.TypeString,
Optional: true,
Computed: true,
Deprecated: "This property has been deprecated and will be removed in v5.0 of the provider. Use display_name property of azurerm_api_management_tag resource.",
}
}

return resource
}

func resourceApiManagementApiOperationTagCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error {
func resourceApiManagementApiOperationTagCreate(d *pluginsdk.ResourceData, meta interface{}) error {
subscriptionId := meta.(*clients.Client).Account.SubscriptionId
tagClient := meta.(*clients.Client).ApiManagement.TagClient
client := meta.(*clients.Client).ApiManagement.ApiOperationTagClient
Expand All @@ -77,29 +82,51 @@ func resourceApiManagementApiOperationTagCreateUpdate(d *pluginsdk.ResourceData,
apiName := getApiName(apiOperationId.ApiId)

id := apioperationtag.NewOperationTagID(subscriptionId, apiOperationId.ResourceGroupName, apiOperationId.ServiceName, apiName, apiOperationId.OperationId, d.Get("name").(string))
tagId := tag.NewTagID(subscriptionId, apiOperationId.ResourceGroupName, apiOperationId.ServiceName, d.Get("name").(string))

// For 4.0 we continue to create the tag if display_name is set (backward compatibility)
displayName := d.Get("display_name").(string)
if !features.FivePointOhBeta() && len(displayName) > 0 {
if d.IsNewResource() {
existing, err := client.TagGetByOperation(ctx, id)
if err != nil {
if !response.WasNotFound(existing.HttpResponse) {
return fmt.Errorf("checking for presence of existing Tag %q: %s", id, err)
}
}

if d.IsNewResource() {
existing, err := client.TagGetByOperation(ctx, id)
if err != nil {
if !response.WasNotFound(existing.HttpResponse) {
return fmt.Errorf("checking for presence of existing Tag %q: %s", id, err)
return tf.ImportAsExistsError("azurerm_api_management_api_operation_tag", id.ID())
}
}

if !response.WasNotFound(existing.HttpResponse) {
return tf.ImportAsExistsError("azurerm_api_management_api_operation_tag", id.ID())
parameters := tag.TagCreateUpdateParameters{
Properties: &tag.TagContractProperties{
DisplayName: d.Get("display_name").(string),
},
}
}

parameters := tag.TagCreateUpdateParameters{
Properties: &tag.TagContractProperties{
DisplayName: d.Get("display_name").(string),
},
}
if _, err := tagClient.CreateOrUpdate(ctx, tagId, parameters, tag.CreateOrUpdateOperationOptions{}); err != nil {
return fmt.Errorf("creating/updating %q: %+v", id, err)
}
} else {
tagAssignmentExist, err := client.TagGetByOperation(ctx, id)
if err != nil {
if !response.WasNotFound(tagAssignmentExist.HttpResponse) {
return fmt.Errorf("checking for presence of Tag Assignment %q: %s", id, err)
}
}

tagId := tag.NewTagID(subscriptionId, apiOperationId.ResourceGroupName, apiOperationId.ServiceName, d.Get("name").(string))
if _, err := tagClient.CreateOrUpdate(ctx, tagId, parameters, tag.CreateOrUpdateOperationOptions{}); err != nil {
return fmt.Errorf("creating/updating %q: %+v", id, err)
if !response.WasNotFound(tagAssignmentExist.HttpResponse) {
return tf.ImportAsExistsError("azurerm_api_management_api_operation_tag", id.ID())
}

tagExists, err := tagClient.Get(ctx, tagId)
if err != nil {
if !response.WasNotFound(tagExists.HttpResponse) {
return fmt.Errorf("checking for presence of Tag %q: %s", id, err)
}
}
}

if _, err := client.TagAssignToOperation(ctx, id); err != nil {
Expand Down Expand Up @@ -139,15 +166,25 @@ func resourceApiManagementApiOperationTagRead(d *pluginsdk.ResourceData, meta in
d.Set("api_operation_id", apioperationtag.NewOperationID(subscriptionId, id.ResourceGroupName, id.ServiceName, id.ApiId, id.OperationId).ID())
d.Set("name", id.TagId)

if model := resp.Model; model != nil {
if props := model.Properties; props != nil {
d.Set("display_name", props.DisplayName)
if !features.FivePointOhBeta() {
if model := resp.Model; model != nil {
if props := model.Properties; props != nil {
d.Set("display_name", props.DisplayName)
}
}
}

return nil
}

func resourceApiManagementApiOperationTagUpdate(d *pluginsdk.ResourceData, meta interface{}) error {
if features.FivePointOhBeta() {
return nil
}

return resourceApiManagementApiOperationTagCreate(d, meta)
}

func resourceApiManagementApiOperationTagDelete(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).ApiManagement.ApiOperationTagClient
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,27 +48,57 @@ func TestAccApiManagementApiOperationTag_requiresImport(t *testing.T) {
})
}

func TestAccApiManagementApiOperationTag_update(t *testing.T) {
func TestAccApiManagementApiOperationTag_basic_withDisplayNameBackwardCompatibility(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_api_management_api_operation_tag", "test")
r := ApiManagementApiOperationTagResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.basic(data),
Config: r.basic_withDisplayNameBackwardCompatibility(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccApiManagementApiOperationTag_requiresImport_withDisplayNameBackwardCompatibility(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_api_management_api_operation_tag", "test")
r := ApiManagementApiOperationTagResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.basic_withDisplayNameBackwardCompatibility(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.RequiresImportErrorStep(r.requiresImport_withDisplayNameBackwardCompatibility),
})
}

func TestAccApiManagementApiOperationTag_update_withDisplayNameBackwardCompatibility(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_api_management_api_operation_tag", "test")
r := ApiManagementApiOperationTagResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.update(data),
Config: r.basic_withDisplayNameBackwardCompatibility(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.basic(data),
Config: r.update_withDisplayNameBackwardCompatibility(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.basic_withDisplayNameBackwardCompatibility(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
Expand All @@ -95,6 +125,34 @@ func (r ApiManagementApiOperationTagResource) basic(data acceptance.TestData) st
return fmt.Sprintf(`
%s

resource "azurerm_api_management_tag" "test" {
api_management_id = azurerm_api_management.test.id
name = "acctest-Tag-%d"
display_name = "Display-Tag"
}

resource "azurerm_api_management_api_operation_tag" "test" {
api_operation_id = azurerm_api_management_api_operation.test.id
name = azurerm_api_management_tag.test.name
}
`, ApiManagementApiOperationResource{}.basic(data), data.RandomInteger)
}

func (r ApiManagementApiOperationTagResource) requiresImport(data acceptance.TestData) string {
return fmt.Sprintf(`
%s

resource "azurerm_api_management_api_operation_tag" "import" {
api_operation_id = azurerm_api_management_api_operation_tag.test.api_operation_id
name = azurerm_api_management_api_operation_tag.test.name
}
`, r.basic(data))
}

func (r ApiManagementApiOperationTagResource) basic_withDisplayNameBackwardCompatibility(data acceptance.TestData) string {
return fmt.Sprintf(`
%s

resource "azurerm_api_management_api_operation_tag" "test" {
api_operation_id = azurerm_api_management_api_operation.test.id
name = "acctest-Op-Tag-%d"
Expand All @@ -103,7 +161,7 @@ resource "azurerm_api_management_api_operation_tag" "test" {
`, ApiManagementApiOperationResource{}.basic(data), data.RandomInteger)
}

func (r ApiManagementApiOperationTagResource) requiresImport(data acceptance.TestData) string {
func (r ApiManagementApiOperationTagResource) requiresImport_withDisplayNameBackwardCompatibility(data acceptance.TestData) string {
return fmt.Sprintf(`
%s

Expand All @@ -112,10 +170,10 @@ resource "azurerm_api_management_api_operation_tag" "import" {
name = azurerm_api_management_api_operation_tag.test.name
display_name = azurerm_api_management_api_operation_tag.test.display_name
}
`, r.basic(data))
`, r.basic_withDisplayNameBackwardCompatibility(data))
}

func (r ApiManagementApiOperationTagResource) update(data acceptance.TestData) string {
func (r ApiManagementApiOperationTagResource) update_withDisplayNameBackwardCompatibility(data acceptance.TestData) string {
return fmt.Sprintf(`
%s

Expand Down
45 changes: 29 additions & 16 deletions website/docs/r/api_management_api_operation_tag.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,40 @@ subcategory: "API Management"
layout: "azurerm"
page_title: "Azure Resource Manager: azurerm_api_management_api_operation_tag"
description: |-
Manages a API Management API Operation Tag.
Manages an API Management API Operation Tag.
---

# azurerm_api_management_api_operation_tag

Manages a API Management API Operation Tag.
Manages the Assignment of an API Management Tag to an Operation.

## 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"
provider "azurerm" {
features {}
}

data "azurerm_resource_group" "example" {
name = "example-resources"
location = "West Europe"
}

data "azurerm_api_management" "example" {
name = "example-apim"
resource_group_name = data.azurerm_resource_group.example.name
}

resource "azurerm_api_management_api" "example" {
name = "example-api"
resource_group_name = data.azurerm_resource_group.example.name
api_management_name = data.azurerm_api_management.example.name
revision = "1"
}

resource "azurerm_api_management_api_operation" "example" {
operation_id = "user-delete"
api_name = data.azurerm_api_management_api.example.name
api_name = 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
display_name = "Delete User Operation"
Expand All @@ -41,10 +55,14 @@ resource "azurerm_api_management_api_operation" "example" {
}
}

resource "azurerm_api_management_tag" "example" {
api_management_id = data.azurerm_api_management.example.id
name = "example-tag"
}

resource "azurerm_api_management_api_operation_tag" "example" {
name = "example-Tag"
name = azurerm_api_management_tag.example.name
api_operation_id = azurerm_api_management_api_operation.example.id
display_name = "example-Tag"
}
```

Expand All @@ -54,11 +72,7 @@ The following arguments are supported:

* `api_operation_id` - (Required) The ID of the API Management API Operation. Changing this forces a new API Management API Operation Tag to be created.

* `name` - (Required) The name which should be used for this API Management API Operation Tag. Changing this forces a new API Management API Operation Tag to be created. The name must be unique in the API Management Service.

---

* `display_name` - (Required) The display name of the API Management API Operation Tag.
* `name` - (Required) The name of the tag. It must be known in the API Management instance. Changing this forces a new API Management API Tag to be created.

## Attributes Reference

Expand All @@ -72,7 +86,6 @@ The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/l

* `create` - (Defaults to 30 minutes) Used when creating the API Management API Operation Tag.
* `read` - (Defaults to 5 minutes) Used when retrieving the API Management API Operation Tag.
* `update` - (Defaults to 30 minutes) Used when updating the API Management API Operation Tag.
* `delete` - (Defaults to 30 minutes) Used when deleting the API Management API Operation Tag.

## Import
Expand Down