Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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 @@ -10,18 +10,20 @@ import (

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema"
"github.com/hashicorp/go-azure-sdk/resource-manager/cognitive/2025-06-01/raiblocklists"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-azurerm/internal/locks"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/cognitive/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
)

type cognitiveRaiBlocklistModel struct {
Name string `tfschema:"name"`
CognitiveAccountId string `tfschema:"cognitive_account_id"`
Description string `tfschema:"description"`
Name string `tfschema:"name"`
CognitiveAccountId string `tfschema:"cognitive_account_id"`
Description string `tfschema:"description"`
Tags map[string]string `tfschema:"tags"`
}

type CognitiveRaiBlocklistResource struct{}
Expand All @@ -34,7 +36,7 @@ func (c CognitiveRaiBlocklistResource) Arguments() map[string]*schema.Schema {
Type: pluginsdk.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringIsNotEmpty,
ValidateFunc: validate.RaiBlocklistName(),
},

"cognitive_account_id": {
Expand All @@ -48,6 +50,7 @@ func (c CognitiveRaiBlocklistResource) Arguments() map[string]*schema.Schema {
Type: pluginsdk.TypeString,
Optional: true,
},
"tags": commonschema.Tags(),
}
}

Expand Down Expand Up @@ -92,6 +95,10 @@ func (c CognitiveRaiBlocklistResource) Create() sdk.ResourceFunc {
payload.Properties.Description = &model.Description
}

if model.Tags != nil {
payload.Tags = pointer.To(model.Tags)
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrapping this in a != nil if block is not necessary. If model.Tags is nil (zero value for map), pointer.To will still return a pointer to this zero value and subsequent JSON serialisation logic will handle this just fine.

Do a codebase search for Tags.*pointer\.To and observe how we never wrap such code in this kind of if block.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


if _, err := client.CreateOrUpdate(ctx, id, *payload); err != nil {
return fmt.Errorf("creating %s: %+v", id, err)
}
Expand Down Expand Up @@ -144,6 +151,10 @@ func (c CognitiveRaiBlocklistResource) Update() sdk.ResourceFunc {
payload.Properties.Description = pointer.To(model.Description)
}

if metadata.ResourceData.HasChange("tags") {
payload.Tags = pointer.To(model.Tags)
}

if _, err := client.CreateOrUpdate(ctx, *id, *payload); err != nil {
return fmt.Errorf("updating %s: %+v", id, err)
}
Expand Down Expand Up @@ -215,6 +226,7 @@ func (c CognitiveRaiBlocklistResource) Read() sdk.ResourceFunc {
if props := model.Properties; props != nil {
state.Description = pointer.From(props.Description)
}
state.Tags = pointer.From(model.Tags)
}

return metadata.Encode(&state)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ resource "azurerm_cognitive_account_rai_blocklist" "test" {
name = "acctest-crb-%d"
cognitive_account_id = azurerm_cognitive_account.test.id
description = "Acceptance test data new azurerm resource"
tags = {
Acceptance = "Test"
Environment = "Dev"
}
}
`, template, data.RandomInteger)
}
Expand All @@ -174,6 +178,11 @@ resource "azurerm_cognitive_account_rai_blocklist" "test" {
name = "acctest-crb-%d"
cognitive_account_id = azurerm_cognitive_account.test.id
description = "Acceptance test data new azurerm resource updated"
tags = {
Acceptance = "TestUpdated"
Environment = "Dev"
Updated = "true"
}
}
`, template, data.RandomInteger)
}
18 changes: 18 additions & 0 deletions internal/services/cognitive/validate/rai_blocklist_name.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright IBM Corp. 2014, 2026
// SPDX-License-Identifier: MPL-2.0

package validate

import (
"regexp"

"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
)

func RaiBlocklistName() pluginsdk.SchemaValidateFunc {
return validation.StringMatch(
regexp.MustCompile("^[a-zA-Z0-9_-]{2,64}$"),
"The RAI Blocklist Name must be between 2 and 64 characters long, contain only alphanumeric characters, hyphens(-) or underscores(_).",
)
}
116 changes: 116 additions & 0 deletions internal/services/cognitive/validate/rai_blocklist_name_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Copyright IBM Corp. 2014, 2026
// SPDX-License-Identifier: MPL-2.0

package validate

import (
"testing"
)

func TestValidateCognitiveServicesRaiBlocklistName(t *testing.T) {
tests := []struct {
name string
input string
valid bool
}{
{
name: "empty name",
input: "",
valid: false,
},
{
name: "Invalid single character",
input: "a",
valid: false,
},
{
name: "Valid two characters",
input: "ab",
valid: true,
},
{
name: "Valid alphanumeric",
input: "hello1",
valid: true,
},
{
name: "Valid contains underscore",
input: "hello_world",
valid: true,
},
{
name: "Valid contains hyphen",
input: "hello-world",
valid: true,
},
{
name: "Valid starts with digit",
input: "1hello",
valid: true,
},
{
name: "Valid starts with underscore",
input: "_hello",
valid: true,
},
{
name: "Valid starts with hyphen",
input: "-hello",
valid: true,
},
{
name: "Valid ends with underscore",
input: "hello_",
valid: true,
},
{
name: "Valid ends with hyphen",
input: "hello-",
valid: true,
},
{
name: "Invalid contains period",
input: "a.bc",
valid: false,
},
{
name: "Invalid contains whitespace",
input: "a bc",
valid: false,
},
{
name: "Invalid contains special character",
input: "a@bc",
valid: false,
},
{
name: "contains slash",
input: "a/bc",
valid: false,
},
{
name: "Valid 64 characters",
input: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789012",
valid: true,
},
{
name: "Invalid starts with period",
input: ".heyo",
valid: false,
},
{
name: "Invalid 65 characters",
input: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890123",
valid: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := RaiBlocklistName()(tt.input, "")
valid := err == nil
if valid != tt.valid {
t.Errorf("Expected valid status %t but got %t for input %s", tt.valid, valid, tt.input)
}
})
}
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice 👍, thank you for adding unit tests

Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ subcategory: "Cognitive Services"
layout: "azurerm"
page_title: "Azure Resource Manager: azurerm_cognitive_account_rai_blocklist"
description: |-
Manages a Cognitive Account Rai Blocklist.
Manages a Microsoft Foundry "Guardrails + Controls" blocklist. Microsoft Foundry was previously known as "Cognitive Account".
---

# azurerm_cognitive_account_rai_blocklist

Manages a Cognitive Account Rai Blocklist.
Manages a Microsoft Foundry "Guardrails + Controls" blocklist. Microsoft Foundry was previously known as "Cognitive Account".

## Example Usage

Expand Down Expand Up @@ -41,6 +41,8 @@ The following arguments are supported:

* `cognitive_account_id` - (Required) The ID of the Cognitive Services Account. Changing this forces a new Cognitive Account Rai Blocklist to be created.

* `tags` - (Optional) A mapping of tags assigned to the resource.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit of scope creep, but I was struggling to correlate "Guardrail + Controls" -> blocklist in portal to this resource. Perhaps you can improve this docs a bit to help our customers.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is fixed


---

* `description` - (Optional) A short description for the Cognitive Account Rai Blocklist.
Expand Down
Loading